{
    "openapi": "3.0.3",
    "info": {
        "title": "RecurPost API",
        "version": "2.0.0",
        "description": "Public REST API of the RecurPost social media scheduling platform.\n\nEvery endpoint is a POST with a JSON body. Call /api/user_login with your account email and API key (from Account Settings, not your password) to receive an access token valid for one hour, then send it as `Authorization: Bearer <token>` on every other call. `Authorization: Basic base64(emailid:pass_key)` and body credentials (emailid + pass_key) are also accepted.\n\nResponses carry X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset headers; a 429 with Retry-After means the per-minute allowance is used up.\n\nEndpoints marked legacy answer errors as HTTP 200 with the real status in the body when called with body or Basic credentials; with a Bearer token every endpoint returns real HTTP status codes.\n\nFull reference with code samples and a playground: https://developers.recurpost.com/",
        "contact": {
            "name": "RecurPost",
            "url": "https://recurpost.com/"
        }
    },
    "servers": [
        {
            "url": "https://social.recurpost.com"
        }
    ],
    "tags": [
        {
            "name": "Authentication",
            "description": "Exchange your API key for a short-lived access token. Every other endpoint accepts that token in the `Authorization: Bearer` header."
        },
        {
            "name": "Workspaces",
            "description": "Workspaces group social accounts, libraries and team members. Every call that works inside a workspace takes an optional `workspace_id`; this module lists the workspaces you can use, describes one, creates new ones and manages their members."
        },
        {
            "name": "Team Roles",
            "description": "The roles of your account and what each one may do: the Roles page. A role is a named set of permission keys plus the notifications its members receive; members are given a role per workspace with `/api/workspace_invite` and `/api/workspace_member_update`. Roles belong to the account owner, so every call here needs the owner's own key."
        },
        {
            "name": "Social Accounts",
            "description": "The social accounts connected to a workspace, the links to connect or reconnect them, click tracking on their short links, and the option lists some networks need when you post (TikTok and YouTube settings, Facebook backgrounds, mention search, Instagram products and audio)."
        },
        {
            "name": "Account & Settings",
            "description": "Your own RecurPost account rather than a connected social profile: profile details and timezone, the plan of the workspace owner with its limits, invoices and storage, the posting queue switch, the X link-credit wallet, custom fields, and the preference pages (email and push notifications, working hours, branding)."
        },
        {
            "name": "Account Groups",
            "description": "Account groups are named sets of social accounts a post can target in one go. Groups belong to the workspace owner, so every call works on the owner's groups whichever workspace you name."
        },
        {
            "name": "Posts",
            "description": "Publish or schedule one-off posts on your social accounts, follow a post's state per account, preview or shorten links, and look up Instagram places to tag. All post calls share one set of content fields with per-network prefixed overrides; the same fields add and update recurring posts under Libraries."
        },
        {
            "name": "Media",
            "description": "Upload images and videos straight to RecurPost storage through a presigned URL, then reference them by URL in the post, draft and library calls, and browse the media already used in the owner's posts."
        },
        {
            "name": "Drafts",
            "description": "Posts saved without a publish time. A draft carries the same content and per-network options as a one-off post made with `/api/post_content`; `/api/draft_schedule` turns it into a scheduled post in place, keeping its id."
        },
        {
            "name": "Queue",
            "description": "Posts waiting to go out. A queue item is one account at one time, identified by a plain integer `id`; the `post_id` groups the items of one post across its accounts. List and read items, move or rewrite one, remove some, move a whole day, publish right now, or retry a failed post."
        },
        {
            "name": "History",
            "description": "What has already gone out: published and failed posts, with the text and media the network received, the permalink on the network and the failure reason. `/api/history_list` covers the whole workspace with filters and paging; `/api/history_data` is the older per-account feed built for polling."
        },
        {
            "name": "Libraries",
            "description": "Libraries hold evergreen posts that RecurPost publishes in rotation on the schedules attached to the library. These endpoints list, create, update and pause libraries, add, read, search and update their posts, move or copy posts between libraries, delete posts, and manage the message variations of a post. /api/add_content_in_library and /api/library_content_update take the content fields of /api/post_content.\nEvery id in this module (`library_id`, post `id`, variation `id`) is an encrypted string handed out by these endpoints; plain numbers are rejected."
        },
        {
            "name": "Library Tools",
            "description": "The tools the app keeps beside a library: posts that expired out of their library, the drafts of a library, find-and-replace across posts, the next-post pointer of every account, and the public share link with the comments clients leave through it.\nIds follow the Libraries module: `library_id`, `content_id`, `account_id` and `account_ids` are encrypted strings handed out by other endpoints. `comment_id`, `position` and the page numbers are plain integers. Endpoints with an `action` parameter are one call per resource; the action picks what happens and which other fields are read."
        },
        {
            "name": "Schedules",
            "description": "Time slots that publish a library's posts to a social account: which library, which account, how often and at what time. A slot is `weekly` (a weekday) or `monthly` (a day of the month), at a fixed time or at the account's best time."
        },
        {
            "name": "RSS Feeds",
            "description": "RSS feeds that fill a library with new articles. A feed is always handled together with the library it feeds: the same feed URL can be attached to several libraries, each with its own approval setting."
        },
        {
            "name": "Import",
            "description": "The import plugin: posts an account has already published on its network, pulled into RecurPost so you can add them to a library as evergreen content. List the accounts the plugin can read, page through what each one has published, then move a batch into a library with optional caption and per-network customisation."
        },
        {
            "name": "Post Labels",
            "description": "Labels are account-wide tags you put on scheduled posts and library posts; the label report groups performance by them. Labels belong to the workspace owner's account, so the same label set is visible in every workspace of that owner. Manage the labels here and attach them to posts with `/api/label_assign`."
        },
        {
            "name": "Content Tools",
            "description": "The tools around composing: hashtag groups per library, bags of tags, watermarks per account or per workspace, testimonial template images, URL shortener accounts and the Instagram product catalog.\n`library_id`, `account_id` and `account_ids` are encrypted strings handed out by other endpoints. `tag_id`, `bag_id`, `template_id`, `shortener_id` and `domain_id` are plain integers from the lists in this module. Catalog, business and product ids are Meta's own numeric ids, sent and returned as strings. Each endpoint is one call per resource with an `action` parameter that picks what happens."
        },
        {
            "name": "Approvals",
            "description": "Library content approval. When a team member adds a post to a library that requires approval, the post waits for its reviewers before it joins the library's rotation. List what is waiting on you or on others, and approve or reject as a reviewer."
        },
        {
            "name": "Workflow Board",
            "description": "The agency workflow board: ideas and posts (cards) moving through the workspace owner's stages to the schedule. The board belongs to the workspace owner; you act as yourself on it, so the role permissions, stage gates and client hand-over rules of the dashboard apply to every call exactly as they do in RecurPost."
        },
        {
            "name": "Workflow Settings",
            "description": "The account's workflow as built in the Workflow Builder: its switches, the Ideas stage and the stages a post passes through on the board before it is scheduled. The workflow belongs to the account owner and applies to every workspace of the account, so every call here needs the owner's own key. Stage and role ids are plain integers."
        },
        {
            "name": "Shared Calendars",
            "description": "The client calendar of a workspace: the shareable link a client opens to review the posts queued for them, the people invited to it, and the comments clients and team members leave on a queued post there. One calendar per workspace; the workflow's client review stage and the urgent approval email both send the client to it."
        },
        {
            "name": "Inbox",
            "description": "The social inbox: comments and mentions on Facebook pages, LinkedIn company pages and Instagram business accounts, direct message conversations on Facebook pages and Instagram business accounts, and reviews of Google Business locations. Reads come from RecurPost's inbox tables (filled by webhooks and syncs); replies, deletes and likes go to the network through the account's own connection, while bookmarks, review marks, assignments and labels live in RecurPost only.\nThree kinds of id appear in this module: an item id (plain integer, one inbox entry: a comment thread, a conversation or a review), a comment id (plain integer, one comment or message inside an item) and a label id (plain integer). Account ids are the encrypted strings from `/api/inbox_accounts`."
        },
        {
            "name": "DM Automations",
            "description": "Comment-to-DM automations for Instagram business accounts. When someone comments on a post (any comment, or one containing a keyword), RecurPost replies publicly and sends them a direct message with an optional button. Mode `anyone` sends the DM to every commenter; `follow_to_unlock` first asks non-followers to follow and sends the link once they do. Daily counters show how each automation performs."
        },
        {
            "name": "Reports",
            "description": "The analytics RecurPost shows on its Reports page, as data or as a PDF: one account's report, the whole workspace's overview, per-post metrics for one account, the PDF produced now or emailed, plus the Pinterest board, Paid Ads and post label reports, the X Wallet purchase of X analytics, and an AI chat over any report. Every report is read live from the network, so calls can take several seconds."
        },
        {
            "name": "Custom Reports",
            "description": "The custom report canvases of a workspace: saved sets of metric and note tiles over chosen accounts, as built on the Custom Reports page, and their PDF. Reports are plain-integer ids scoped to the workspace; tiles are validated here the way the in-app canvas validates them."
        },
        {
            "name": "AI",
            "description": "RecurPost's AI assistant through the API: write post text in a multi-turn chat, generate an image from a prompt, read the AI credit counters, pull hashtags for a text, suggest variations of a library post, write from the app's templates and special-day calendar, draft a week of posts, copy an AI result into libraries and manage the brand voice the AI writes with. Text and image generation spend the AI credits of the workspace owner's plan or add-on."
        }
    ],
    "paths": {
        "/api/user_login": {
            "post": {
                "tags": [
                    "Authentication"
                ],
                "summary": "Verify your API key and receive an access token valid for one hour.",
                "description": "Checks your account email and API key and returns an access token. Send the token as `Authorization: Bearer <token>` on every other call. Tokens live for one hour; there is no refresh token, call this endpoint again to get a new one.\nThe API key is not your account password. Generate it under Account Settings in RecurPost. Regenerating the key revokes every token issued with the old one.\n\nLegacy endpoint: with body or Basic credentials errors arrive as HTTP 200 with the real status in the body field `status`. With a Bearer token it returns real HTTP status codes.",
                "operationId": "user_login",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "emailid": {
                                        "type": "string",
                                        "format": "email",
                                        "description": "Email address of your RecurPost account.",
                                        "example": "you@example.com"
                                    },
                                    "pass_key": {
                                        "type": "string",
                                        "description": "Your API key from Account Settings. `zapier_key` is accepted as an alias. You can also send both values as `Authorization: Basic base64(emailid:pass_key)` instead of the body.",
                                        "example": "your_api_key"
                                    }
                                },
                                "required": [
                                    "emailid",
                                    "pass_key"
                                ],
                                "example": {
                                    "emailid": "you@example.com",
                                    "pass_key": "your_api_key"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "user_info": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted user id."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "First and last name."
                                                },
                                                "email": {
                                                    "type": "string",
                                                    "description": "Account email."
                                                }
                                            }
                                        },
                                        "token": {
                                            "type": "string",
                                            "description": "64-character access token. Shown once; store it on your side."
                                        },
                                        "expires_at": {
                                            "type": "string",
                                            "format": "date-time",
                                            "description": "Expiry time in UTC, ISO 8601."
                                        },
                                        "expires_in": {
                                            "type": "integer",
                                            "description": "Seconds until expiry, always 3600."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "user_info": {
                                        "id": "nX2k9Qp7Lw==",
                                        "name": "Jane Doe",
                                        "email": "you@example.com"
                                    },
                                    "token": "3f9c1b7e5a2d4c8f6e0b1a9d7c5e3f2a4b6d8c0e1f3a5b7d9c2e4f6a8b0d1c3e",
                                    "expires_at": "2026-10-22T11:30:00Z",
                                    "expires_in": 3600
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (emailid or pass_key missing.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "We could not authenticate the user's RecurPost credentials. (Email and key do not match. Repeated failures lock the email for a while.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Too many failed attempts. Please try again after ... (The email is locked after repeated failed logins.)\n\nToo many login attempts from this address. Try again in N seconds. (More than 120 login or signup calls from one IP address in a minute.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                },
                "security": []
            }
        },
        "/api/workspace_list": {
            "post": {
                "tags": [
                    "Workspaces"
                ],
                "summary": "List the workspaces you own or that are shared with you.",
                "description": "Returns every workspace you are a member of: the ones you own and the ones other accounts shared with you. The `ws_id` values are what you pass as `workspace_id` to the other endpoints; when a call omits `workspace_id` the workspace flagged `is_default` is used.\n\nEmpty body instead of an error: When the app cannot read the list (for example the account has no workspace row) the call answers HTTP 200 with an empty JSON array `[]` and no `status` field. Treat a body without `workspace_list` as a failure.\n\nUsing workspace_id: Pass `ws_id` as `workspace_id` to any endpoint that lists it. A shared workspace runs under its owner's plan, timezone and limits, and some actions (queue pause, invites, client report emails) stay with the owner.\n\nLegacy endpoint: with body or Basic credentials errors arrive as HTTP 200 with the real status in the body field `status`. With a Bearer token it returns real HTTP status codes.",
                "operationId": "workspace_list",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": []
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "workspace_list": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "ws_id": {
                                                        "type": "string",
                                                        "description": "Encrypted workspace id. Pass it as `workspace_id` to the other endpoints."
                                                    },
                                                    "ws_name": {
                                                        "type": "string",
                                                        "description": "Workspace name."
                                                    },
                                                    "is_default": {
                                                        "type": "integer",
                                                        "description": "`1` for the workspace created at signup, which is used when a call omits `workspace_id`; `0` otherwise."
                                                    },
                                                    "ownership": {
                                                        "type": "string",
                                                        "description": "`own` when the workspace is yours, `shared` when another account invited you into it."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "workspace_list": [
                                        {
                                            "ws_id": "wS1dF2gH==",
                                            "ws_name": "Mine",
                                            "is_default": 1,
                                            "ownership": "own"
                                        },
                                        {
                                            "ws_id": "nX2k9Qp7Lw==",
                                            "ws_name": "Agency",
                                            "is_default": 0,
                                            "ownership": "shared"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workspace_details": {
            "post": {
                "tags": [
                    "Workspaces"
                ],
                "summary": "Read one workspace: libraries, accounts, members, pending invites and account manager.",
                "description": "Returns the workspace record with everything attached to it. A member of a shared workspace reads the same libraries, accounts and members; the owner additionally sees the pending invites, the roles of the account (the values `/api/workspace_invite` accepts) and the client report emails, and gets `client_email` filled in. For a member `client_email` is `null` and `pending_invites` is empty.\n\nPlain ids for people: User and role ids in this module are plain integers, not encrypted strings. Workspace, library and account ids stay encrypted.",
                "operationId": "workspace_details",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "workspace": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted workspace id."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Workspace name."
                                                },
                                                "is_default": {
                                                    "type": "boolean",
                                                    "description": "`true` for the signup workspace of its owner."
                                                },
                                                "is_owner": {
                                                    "type": "boolean",
                                                    "description": "`true` when the workspace is yours."
                                                },
                                                "owner": {
                                                    "type": "object",
                                                    "properties": {
                                                        "id": {
                                                            "type": "string",
                                                            "description": "Encrypted user id of the owner."
                                                        },
                                                        "name": {
                                                            "type": "string",
                                                            "description": "Owner's name."
                                                        }
                                                    }
                                                },
                                                "timezone": {
                                                    "type": "string",
                                                    "description": "Owner's timezone; dates in this workspace are shown in it."
                                                },
                                                "account_manager": {
                                                    "type": "object",
                                                    "description": "The member set as account manager, as `{id, name, email, role}`, or `null` when none is set."
                                                },
                                                "client_email": {
                                                    "type": "string",
                                                    "description": "Default client email for approvals and reports. Owner only; `null` for a member."
                                                },
                                                "created_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "description": "When the workspace was created, UTC."
                                                }
                                            }
                                        },
                                        "libraries": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted library id (see `/api/library_list`)."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Library name."
                                                    },
                                                    "color": {
                                                        "type": "string",
                                                        "description": "Hex color of the library."
                                                    }
                                                }
                                            }
                                        },
                                        "accounts": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted social account id."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Account name."
                                                    },
                                                    "network": {
                                                        "type": "string",
                                                        "description": "Network key, e.g. `facebook`, `twitter`, `linkedin`, `instagram`."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "`active`, `paused` or `needs_reconnection`."
                                                    }
                                                }
                                            }
                                        },
                                        "members": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted user id of an active member. The owner is not listed."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Member's name."
                                                    },
                                                    "email": {
                                                        "type": "string",
                                                        "format": "email",
                                                        "description": "Member's email."
                                                    },
                                                    "role": {
                                                        "type": "object",
                                                        "description": "`{id, name}` of the member's role in this workspace, or `null`."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "Always `active` here."
                                                    },
                                                    "is_account_manager": {
                                                        "type": "boolean",
                                                        "description": "`true` for the account manager."
                                                    }
                                                }
                                            }
                                        },
                                        "pending_invites": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted user id of an invited person who has not accepted yet. Pass it as `user_id` to `/api/workspace_invite` with `action=resend`. Owner only."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Invitee's name."
                                                    },
                                                    "email": {
                                                        "type": "string",
                                                        "format": "email",
                                                        "description": "Invitee's email."
                                                    },
                                                    "role": {
                                                        "type": "object",
                                                        "description": "`{id, name}` of the role they were invited with, or `null`."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "Always `pending`."
                                                    },
                                                    "invited_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When the invite was sent, UTC."
                                                    }
                                                }
                                            }
                                        },
                                        "roles": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain role id. Owner only. Either the id or the name is accepted as `role` by `/api/workspace_invite` and `/api/workspace_create`."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Role name."
                                                    },
                                                    "description": {
                                                        "type": "string",
                                                        "description": "Role description, may be empty."
                                                    },
                                                    "members": {
                                                        "type": "integer",
                                                        "description": "How many workspace memberships across the account use this role."
                                                    }
                                                }
                                            }
                                        },
                                        "client_report_emails": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain id of the scheduled report, for `/api/workspace_report_emails`. Owner only."
                                                    },
                                                    "email": {
                                                        "type": "string",
                                                        "format": "email",
                                                        "description": "Address that receives the scheduled client report. Owner only."
                                                    },
                                                    "frequency": {
                                                        "type": "string",
                                                        "description": "`weekly` or `monthly`."
                                                    },
                                                    "day": {
                                                        "type": "integer",
                                                        "description": "Day the report goes out: weekday number 1 to 7 for weekly, day of month 1 to 28 for monthly."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "`false` when the report is switched off."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "workspace": {
                                        "id": "nX2k9Qp7Lw==",
                                        "name": "Agency",
                                        "is_default": false,
                                        "is_owner": true,
                                        "owner": {
                                            "id": "Zk4pL2wQ9A==",
                                            "name": "Jane Doe"
                                        },
                                        "timezone": "Asia/Kolkata",
                                        "account_manager": {
                                            "id": "Mb2rQ8vK1g==",
                                            "name": "Mem Ber",
                                            "email": "mem@example.com",
                                            "role": {
                                                "id": 7,
                                                "name": "Designer"
                                            }
                                        },
                                        "client_email": "client@example.com",
                                        "created_at": "2026-09-01 09:00:00"
                                    },
                                    "libraries": [
                                        {
                                            "id": "lB5cD6eF==",
                                            "name": "Evergreen",
                                            "color": "#abcdef"
                                        }
                                    ],
                                    "accounts": [
                                        {
                                            "id": "aB3dE5fG==",
                                            "name": "My Page",
                                            "network": "facebook",
                                            "status": "active"
                                        }
                                    ],
                                    "members": [
                                        {
                                            "id": "Mb2rQ8vK1g==",
                                            "name": "Mem Ber",
                                            "email": "mem@example.com",
                                            "role": {
                                                "id": 7,
                                                "name": "Designer"
                                            },
                                            "status": "active",
                                            "is_account_manager": true
                                        }
                                    ],
                                    "pending_invites": [
                                        {
                                            "id": "Pd5nT1zX7w==",
                                            "name": "Pen Ding",
                                            "email": "pen@example.com",
                                            "role": {
                                                "id": 7,
                                                "name": "Designer"
                                            },
                                            "status": "pending",
                                            "invited_at": "2026-10-10 14:20:00"
                                        }
                                    ],
                                    "roles": [
                                        {
                                            "id": 7,
                                            "name": "Designer",
                                            "description": "Makes things",
                                            "members": 2
                                        }
                                    ],
                                    "client_report_emails": [
                                        {
                                            "id": 12,
                                            "email": "report@example.com",
                                            "frequency": "weekly",
                                            "day": 1,
                                            "active": true
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workspace_create": {
            "post": {
                "tags": [
                    "Workspaces"
                ],
                "summary": "Create a workspace, optionally with libraries, accounts and invites.",
                "description": "Creates a workspace owned by you. You can attach existing libraries and social accounts of your account in the same call and invite people by email, each with an optional role. The libraries, accounts and roles are all checked before anything is written. Invites are sent after the workspace exists and a failed invite does not undo it: the result lists them in `invites_failed`.\nCreating workspaces needs a paid plan.\n\nInvites create accounts and send mail: An invited address that has no RecurPost account gets one, with a welcome email carrying a temporary password, exactly as an invite from the app does. Addresses already in RecurPost get an invitation email. Check `invites_failed` rather than assuming every invite went out.",
                "operationId": "workspace_create",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "description": "Workspace name, trimmed. Must not match one of your other workspaces.",
                                        "example": "Agency"
                                    },
                                    "library_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted library ids from `/api/library_list` to attach: a JSON array, an array of fields, or one string with ids separated by commas. Every library must be yours.",
                                        "example": [
                                            "lB5cD6eF=="
                                        ]
                                    },
                                    "account_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted social account ids from `/api/social_account_list` to attach, in the same forms. Every account must be yours.",
                                        "example": [
                                            "aB3dE5fG=="
                                        ]
                                    },
                                    "invites": {
                                        "type": "array",
                                        "items": [],
                                        "description": "People to invite: a JSON array (or comma-separated string) of email addresses, or of objects `{\"email\": \"...\", \"role\": \"...\"}`. `role` is a role id or name from `/api/workspace_details`, case-insensitive; omit it or send `0` for no role. Both forms can be mixed in one array.",
                                        "example": [
                                            {
                                                "email": "a@example.com",
                                                "role": "Designer"
                                            },
                                            "b@example.com"
                                        ]
                                    }
                                },
                                "required": [
                                    "name"
                                ],
                                "example": {
                                    "name": "Agency"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Workspace created`."
                                        },
                                        "workspace": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted id of the new workspace; use it as `workspace_id`."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "The name as stored."
                                                }
                                            }
                                        },
                                        "invites_sent": {
                                            "type": "integer",
                                            "description": "Invites that went out."
                                        },
                                        "invites_failed": {
                                            "type": "array",
                                            "items": {
                                                "type": "string",
                                                "description": "One entry per invite the app refused, as `email (reason)`, e.g. a seat already taken or the team member limit of your plan."
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Workspace created",
                                    "workspace": {
                                        "id": "nX2k9Qp7Lw==",
                                        "name": "Agency"
                                    },
                                    "invites_sent": 1,
                                    "invites_failed": [
                                        "b@example.com (This user has already been invited for this workspace.)"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (name is missing or blank.)\n\ninvites must hold valid email addresses. (An invite has no valid email.)\n\nFailed to create workspace. Please try again. (The app could not write the workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "library_ids must be libraries of your account. (An id does not decrypt or the library belongs to someone else.)\n\naccount_ids must be social accounts of your account. (An id does not decrypt or the account belongs to someone else.)\n\nYour current plan does not allow you to create a workspace. Please upgrade to add a new workspace. (The account is on a free plan (the upgrade wording varies with the plan).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Role 'X' is not one of this account's roles; see workspace_details. (An invite names a role id or name you do not have.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "You already have a workspace with this name. (The name is taken among your workspaces.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workspace_members": {
            "post": {
                "tags": [
                    "Workspaces"
                ],
                "summary": "Members of a workspace with role and status, and the approvers you can send content to.",
                "description": "Returns the active members of the workspace. The owner also gets the pending invites. A member of a shared workspace gets `approvers` instead: the other people in the workspace, owner flagged, which are the users library content can be sent to for approval. For the owner `approvers` is empty.",
                "operationId": "workspace_members",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "workspace_id": {
                                            "type": "string",
                                            "description": "Encrypted id of the workspace read."
                                        },
                                        "members": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted user id of an active member. The owner is not listed."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Member's name."
                                                    },
                                                    "email": {
                                                        "type": "string",
                                                        "format": "email",
                                                        "description": "Member's email."
                                                    },
                                                    "role": {
                                                        "type": "object",
                                                        "description": "`{id, name}` of the member's role in this workspace, or `null`."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "Always `active`."
                                                    },
                                                    "is_account_manager": {
                                                        "type": "boolean",
                                                        "description": "`true` for the account manager."
                                                    }
                                                }
                                            }
                                        },
                                        "pending_invites": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "description": "Invited people who have not accepted yet, same shape as in `/api/workspace_details` (`id, name, email, role, status, invited_at`). Empty for a member."
                                            }
                                        },
                                        "approvers": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted user id of a person you can send content to for approval. Empty for the owner."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Approver's name."
                                                    },
                                                    "email": {
                                                        "type": "string",
                                                        "format": "email",
                                                        "description": "Approver's email."
                                                    },
                                                    "is_owner": {
                                                        "type": "boolean",
                                                        "description": "`true` when the approver owns the workspace."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "workspace_id": "nX2k9Qp7Lw==",
                                    "members": [
                                        {
                                            "id": "Zk4pL2wQ9A==",
                                            "name": "Big Boss",
                                            "email": "boss@example.com",
                                            "role": null,
                                            "status": "active",
                                            "is_account_manager": false
                                        }
                                    ],
                                    "pending_invites": [],
                                    "approvers": [
                                        {
                                            "id": "Zk4pL2wQ9A==",
                                            "name": "Big Boss",
                                            "email": "boss@example.com",
                                            "is_owner": true
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workspace_invite": {
            "post": {
                "tags": [
                    "Workspaces"
                ],
                "summary": "Invite a member by email, or send a pending invite again.",
                "description": "With `action=invite` (the default) adds a person to the workspace by email with an optional role. An address without a RecurPost account gets one plus a welcome email, as in the app; an existing user gets an invitation email and shows up in `pending_invites` until they accept. With `action=resend` mails the invite again to a pending member named by `user_id`.\nOwner only, and only on workspaces you created: the signup workspace cannot take members.\n\nSends email, may create an account: Every successful call sends mail. An unknown address becomes a RecurPost user with a temporary password before the invite is recorded, so do not use this endpoint to test addresses.\n\nRemoving members: Roles and the account manager flag are changed with `/api/workspace_member_update`; a member is removed with `/api/workspace_member_remove`.",
                "operationId": "workspace_invite",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "email": {
                                        "type": "string",
                                        "format": "email",
                                        "description": "Required when `action=invite`: address to invite.",
                                        "example": "new@example.com"
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "`invite` adds a member, `resend` mails a pending invite again. Case does not matter.",
                                        "enum": [
                                            "invite",
                                            "resend"
                                        ],
                                        "default": "invite",
                                        "example": "invite"
                                    },
                                    "role": {
                                        "type": "string",
                                        "description": "With `action=invite`: a role id or role name from `/api/workspace_details`, case-insensitive. Omit, or send `0`, for no role.",
                                        "example": "Designer"
                                    },
                                    "user_id": {
                                        "type": "string",
                                        "description": "Required when `action=resend`: encrypted user id from `pending_invites[].id` of `/api/workspace_details` or `/api/workspace_members`.",
                                        "example": "Pd5nT1zX7w=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. In practice always send it: the default (signup) workspace cannot take members.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "email"
                                ],
                                "example": {
                                    "email": "new@example.com"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Invited` after an invite, `Invite resent` after a resend."
                                        },
                                        "member": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted user id of the invited person. Invite only."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Their name, which may be just the first name for a freshly created account."
                                                },
                                                "email": {
                                                    "type": "string",
                                                    "format": "email",
                                                    "description": "The address invited."
                                                },
                                                "role": {
                                                    "type": "object",
                                                    "description": "`{id, name}` of the role given, or `null`."
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "`pending` until they accept; `active` straight away when they already are an accepted member of your team in another workspace."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Invited",
                                    "member": {
                                        "id": "Nw4hJ6cF3Q==",
                                        "name": "New",
                                        "email": "new@example.com",
                                        "role": {
                                            "id": 7,
                                            "name": "Designer"
                                        },
                                        "status": "pending"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "action must be invite or resend. (action is another word.)\n\nBad Request Please try again later (email is missing on an invite, or user_id is missing on a resend.)\n\nemail must be a valid email address. (email is not a valid address.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nYou can not invite yourself. (email is your own address.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can invite members. (The workspace belongs to someone else.)\n\nThe signup workspace cannot take members; invite them to a workspace you created. (The workspace is your default one.)\n\nYou have already invited as many team members as your plan allows. Please upgrade to invite more members. (Inviting someone new to your team would exceed the plan's team member limit (the upgrade wording varies with the plan).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nThat user has no pending invite in this workspace. (action=resend and user_id is not in pending_invites.)\n\nRole 'X' is not one of this account's roles; see workspace_details. (role is not one of your role ids or names.)\n\nSomething went wrong (The app could not create the account for a new address; its own error text is relayed when it has one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This user has already been invited for this workspace. (The address is already a member or pending in this workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workspace_update": {
            "post": {
                "tags": [
                    "Workspaces"
                ],
                "summary": "Rename a workspace, set or clear its client email, or switch members to seeing only their own posts.",
                "description": "Changes the settings of one workspace. Send any of `name`, `client_email` and `show_own_posts`; fields left out keep their value. `client_email` is the default address approvals and client reports go to, and a blank string clears it. `show_own_posts` on means team members see only the posts they created in this workspace.\nOwner only: the key must belong to the workspace owner.\n\nFields are applied one by one: Each field is a separate call inside RecurPost, applied in the order name, client_email, show_own_posts. When a later one fails, the earlier ones stay applied and the error names the failed one.",
                "operationId": "workspace_update",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "description": "New workspace name, 1 to 100 characters. At least one of `name`, `client_email` or `show_own_posts` must be sent.",
                                        "example": "Agency clients"
                                    },
                                    "client_email": {
                                        "type": "string",
                                        "format": "email",
                                        "description": "Default client email of the workspace. Send an empty string to clear it.",
                                        "example": "client@example.com"
                                    },
                                    "show_own_posts": {
                                        "type": "boolean",
                                        "description": "`true` so members see only their own posts in this workspace, `false` so they see every post.",
                                        "example": false
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Workspace updated.`"
                                        },
                                        "workspace": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted workspace id."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Name after the update."
                                                },
                                                "client_email": {
                                                    "type": "string",
                                                    "description": "Default client email, empty when none is set."
                                                },
                                                "show_own_posts": {
                                                    "type": "boolean",
                                                    "description": "`true` when members see only their own posts."
                                                },
                                                "is_default": {
                                                    "type": "boolean",
                                                    "description": "`true` for the signup workspace."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Workspace updated.",
                                    "workspace": {
                                        "id": "nX2k9Qp7Lw==",
                                        "name": "Agency clients",
                                        "client_email": "client@example.com",
                                        "show_own_posts": false,
                                        "is_default": false
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nNothing to update: send name, client_email or show_own_posts. (None of the three fields is in the request.)\n\nname must be 1 to 100 characters. (name is blank or longer than 100 characters.)\n\nclient_email must be a valid email address, or blank to clear it. (client_email is not an address and not empty.)\n\nSomething went wrong (The app refused the change; its own text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can change workspace settings. (The workspace belongs to someone else.)\n\nYou need to upgrade your plan to complete the request! (The owner is on a free plan (the text says purchase a plan on a trial).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workspace_clone": {
            "post": {
                "tags": [
                    "Workspaces"
                ],
                "summary": "Create a copy of a workspace with the same libraries, accounts and watermark.",
                "description": "Creates a new workspace named `Copy of <name>` that links the same libraries and social accounts as the original and carries its watermark settings. Members, the account manager, the client email and the client report recipients are not copied, as in the app. The libraries and accounts are shared with the original, not duplicated.\nOwner only: the key must belong to the workspace owner.\n\nCounts as a new workspace: The copy is a workspace like any other and counts against the plan's workspace allowance. Rename it with `/api/workspace_update`.",
                "operationId": "workspace_clone",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. This is the workspace that is copied.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Workspace cloned.`"
                                        },
                                        "workspace": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted id of the new workspace."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Name of the new workspace, `Copy of` plus the original name."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Workspace cloned.",
                                    "workspace": {
                                        "id": "pL7mN2qR4s==",
                                        "name": "Copy of Agency"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nSomething went wrong (The app could not create the copy; its own text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can clone a workspace. (The workspace belongs to someone else.)\n\nYou need to upgrade your plan to complete the request! (The owner is on a free plan (the text says purchase a plan on a trial).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workspace_delete": {
            "post": {
                "tags": [
                    "Workspaces"
                ],
                "summary": "Delete a workspace; its libraries and accounts are unlinked, not deleted.",
                "description": "Deletes the workspace. Its links to libraries, social accounts, members and client report recipients go; the libraries and accounts themselves stay in the account and remain in the other workspaces they belong to. The signup (default) workspace cannot be deleted.\nOwner only, and `confirm=true` is required.\n\nNot reversible: Members lose access to the workspace at once and the queue of its accounts keeps running from the accounts' other workspaces. There is no undo; clone first if in doubt.",
                "operationId": "workspace_delete",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be `true`; the call is refused without it.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. In practice always send it: the default workspace cannot be deleted.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "confirm"
                                ],
                                "example": {
                                    "confirm": true
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Workspace deleted.`"
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Workspace deleted."
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nSend confirm=true to delete the workspace; its libraries and social accounts are unlinked, not deleted. (confirm is missing or not true.)\n\nSomething went wrong (The app could not delete; its own text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can delete a workspace. (The workspace belongs to someone else.)\n\nThe signup workspace cannot be deleted. (The workspace is the default one created at signup.)\n\nYou are not authorized to delete this workspace! (The app refused the delete.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workspace_member_update": {
            "post": {
                "tags": [
                    "Workspaces"
                ],
                "summary": "Change a member's role or make them the account manager of a workspace.",
                "description": "Changes an active member of the workspace: `role` gives them another role (an id or name from `/api/workspace_details`, blank or `0` for no role) and `account_manager` makes them the account manager (`true`) or takes that off them (`false`). Send one or both; a field left out keeps its value. The member must already be active; invite people with `/api/workspace_invite`.\nOwner only: the key must belong to the workspace owner.\n\nRole first, then account manager: When both fields are sent the role is changed first. If the account manager change then fails, the new role stays.\n\nNotifications: A role change and an account manager change send the member the same notifications they would get from Manage Team in the app.",
                "operationId": "workspace_member_update",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "member_id": {
                                        "type": "string",
                                        "description": "Encrypted user id of an active member, from `members[].id` of `/api/workspace_members`.",
                                        "example": "Mb2rQ8vK1g=="
                                    },
                                    "role": {
                                        "type": "string",
                                        "description": "Role id or role name from `/api/workspace_details`, case-insensitive. Send an empty string or `0` to leave the member without a role. At least one of `role` and `account_manager` must be sent.",
                                        "example": "Designer"
                                    },
                                    "account_manager": {
                                        "type": "boolean",
                                        "description": "`true` makes this member the workspace's account manager (replacing the current one), `false` removes them from that position.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. In practice always send it: the default workspace has no members.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "member_id"
                                ],
                                "example": {
                                    "member_id": "Mb2rQ8vK1g=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Member updated.`"
                                        },
                                        "member": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted user id of the member."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Member's name."
                                                },
                                                "email": {
                                                    "type": "string",
                                                    "format": "email",
                                                    "description": "Member's email."
                                                },
                                                "role": {
                                                    "type": "object",
                                                    "description": "`{id, name}` of the role after the update, or `null`."
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "Always `active`."
                                                },
                                                "is_account_manager": {
                                                    "type": "boolean",
                                                    "description": "`true` when the member is now the account manager."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Member updated.",
                                    "member": {
                                        "id": "Mb2rQ8vK1g==",
                                        "name": "Mem Ber",
                                        "email": "mem@example.com",
                                        "role": {
                                            "id": 7,
                                            "name": "Designer"
                                        },
                                        "status": "active",
                                        "is_account_manager": true
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nmember_id is required: send members[].id from workspace_details unchanged (it is an encrypted string). (member_id is missing, empty, null or not an encrypted id (for example a plain number).)\n\nNothing to update: send role or account_manager. (Neither field is in the request.)\n\nSomething went wrong (The app refused the change for another reason; its own text is relayed, for example `Selected person is not a member of this workspace.`)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can manage members. (The workspace belongs to someone else.)\n\nYou are not authorized to manage this workspace! (The app refused the change.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nmember_id is not an active member of workspace \"test 2\"; see workspace_members, and pass workspace_id when the member is in another workspace. (member_id is the owner, a pending invite or belongs to another workspace. The workspace named is the one checked: your signup default when workspace_id is omitted.)\n\nRole 'X' is not one of this account's roles; see workspace_details. (role is not one of your role ids or names.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workspace_member_remove": {
            "post": {
                "tags": [
                    "Workspaces"
                ],
                "summary": "Remove a member from a workspace.",
                "description": "Removes an active member from the workspace. Their open workflow cards are handed over as in the app (same role, then the account manager, then the owner), and when this was the last of your workspaces they were in, their team seat is released. The person keeps their RecurPost account.\nOwner only, and `confirm=true` is required.\n\nSeats: A member who stays in another of your workspaces keeps their seat. Only the last removal frees it for a new invite.",
                "operationId": "workspace_member_remove",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "member_id": {
                                        "type": "string",
                                        "description": "Encrypted user id of an active member, from `members[].id` of `/api/workspace_members`. Pending invites cannot be removed here.",
                                        "example": "Mb2rQ8vK1g=="
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be `true`; the call is refused without it.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. In practice always send it: the default workspace has no members.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "member_id",
                                    "confirm"
                                ],
                                "example": {
                                    "member_id": "Mb2rQ8vK1g==",
                                    "confirm": true
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Member removed.`"
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Member removed."
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nmember_id is required: send members[].id from workspace_details unchanged (it is an encrypted string). (member_id is missing, empty, null or not an encrypted id (for example a plain number).)\n\nSend confirm=true to remove the member; their cards are reassigned and their seat is released when this was their last workspace. (confirm is missing or not true.)\n\nSomething went wrong (The app could not remove the member; its own text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can remove members. (The workspace belongs to someone else.)\n\nYou are not authorized to manage this workspace! (The app refused the removal.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nmember_id is not an active member of workspace \"test 2\"; see workspace_members, and pass workspace_id when the member is in another workspace. (member_id is the owner, a pending invite or belongs to another workspace. The workspace named is the one checked: your signup default when workspace_id is omitted.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workspace_social_accounts": {
            "post": {
                "tags": [
                    "Workspaces"
                ],
                "summary": "Add social accounts to a workspace or remove them from it.",
                "description": "With `action=add` links the given social accounts to the workspace; accounts already in it are skipped. Each newly linked account receives the workspace watermark. With `action=remove` unlinks them from this workspace and drops that watermark; accounts not in the workspace are skipped. The accounts themselves and their queues in other workspaces are untouched.\nOwner only: the key must belong to the workspace owner, and the accounts must be the owner's.\n\nRemoval cancels nothing by itself: Unlinking an account from a workspace does not delete its schedules or queued posts; it only takes the account out of this workspace's view and watermark. Use `/api/schedule_delete` for the slots.\n\nThe signup workspace: The default workspace created at signup is meant to hold every account of the owner; scope accounts with the workspaces you created.",
                "operationId": "workspace_social_accounts",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "`add` or `remove`. Case does not matter.",
                                        "enum": [
                                            "add",
                                            "remove"
                                        ],
                                        "example": "add"
                                    },
                                    "account_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted social account ids from `/api/social_account_list`: one id, a comma-separated string or an array, at most 50.",
                                        "example": [
                                            "aB3dE5fG==",
                                            "hI6jK8lM=="
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "action",
                                    "account_ids"
                                ],
                                "example": {
                                    "action": "add",
                                    "account_ids": [
                                        "aB3dE5fG==",
                                        "hI6jK8lM=="
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Added.` or `Removed.`"
                                        },
                                        "added": {
                                            "type": "array",
                                            "items": {
                                                "type": "string",
                                                "description": "Encrypted ids of the accounts actually linked by this call (action add). Accounts that were already in the workspace are not listed."
                                            }
                                        },
                                        "removed": {
                                            "type": "array",
                                            "items": {
                                                "type": "string",
                                                "description": "Encrypted ids of the accounts actually unlinked (action remove). Accounts that were not in the workspace are not listed."
                                            }
                                        },
                                        "total": {
                                            "type": "integer",
                                            "description": "How many social accounts the workspace holds after the call."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Added.",
                                    "added": [
                                        "aB3dE5fG=="
                                    ],
                                    "total": 4
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\naction must be add or remove. (action is missing or another word.)\n\naccount_ids must hold at least one id. (account_ids is empty or one of the values does not decrypt to an id.)\n\nAt most 50 ids per call; N were sent. (More than 50 ids; N is the count sent.)\n\nSomething went wrong (The app could not unlink an account; its own text is relayed when it sent one. Accounts handled before the failure stay removed.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can change what a workspace holds. (The workspace belongs to someone else.)\n\naccount_ids must belong to the workspace owner's account. (An id is not one of the owner's social accounts.)\n\nYou are not authorized to manage this workspace! (The app refused a removal.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workspace_libraries": {
            "post": {
                "tags": [
                    "Workspaces"
                ],
                "summary": "Add libraries to a workspace or remove them from it.",
                "description": "With `action=add` links the given libraries to the workspace; libraries already in it are skipped. With `action=remove` unlinks them from this workspace; libraries not in the workspace are skipped. The libraries, their posts and their schedules are untouched.\nOwner only: the key must belong to the workspace owner, and the libraries must be the owner's.\n\nSchedules keep running: A library unlinked from a workspace still publishes through its schedules; it just stops showing in this workspace. Delete its slots with `/api/schedule_delete` if that is not wanted.",
                "operationId": "workspace_libraries",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "`add` or `remove`. Case does not matter.",
                                        "enum": [
                                            "add",
                                            "remove"
                                        ],
                                        "example": "add"
                                    },
                                    "library_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted library ids from `/api/library_list`: one id, a comma-separated string or an array, at most 50.",
                                        "example": [
                                            "lB5cD6eF=="
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "action",
                                    "library_ids"
                                ],
                                "example": {
                                    "action": "add",
                                    "library_ids": [
                                        "lB5cD6eF=="
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Added.` or `Removed.`"
                                        },
                                        "added": {
                                            "type": "array",
                                            "items": {
                                                "type": "string",
                                                "description": "Encrypted ids of the libraries actually linked by this call (action add)."
                                            }
                                        },
                                        "removed": {
                                            "type": "array",
                                            "items": {
                                                "type": "string",
                                                "description": "Encrypted ids of the libraries actually unlinked (action remove)."
                                            }
                                        },
                                        "total": {
                                            "type": "integer",
                                            "description": "How many libraries the workspace holds after the call."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Removed.",
                                    "removed": [
                                        "lB5cD6eF=="
                                    ],
                                    "total": 2
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\naction must be add or remove. (action is missing or another word.)\n\nlibrary_ids must hold at least one id. (library_ids is empty or one of the values does not decrypt to an id.)\n\nAt most 50 ids per call; N were sent. (More than 50 ids; N is the count sent.)\n\nSomething went wrong (The app could not unlink a library; its own text is relayed when it sent one. Libraries handled before the failure stay removed.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can change what a workspace holds. (The workspace belongs to someone else.)\n\nlibrary_ids must belong to the workspace owner's account. (An id is not one of the owner's libraries.)\n\nYou are not authorized to manage this workspace! (The app refused a removal.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workspace_report_emails": {
            "post": {
                "tags": [
                    "Workspaces"
                ],
                "summary": "List, add, update or delete the client report recipients of a workspace.",
                "description": "The people who receive the scheduled client report of the workspace by email. With `action=list` (the default) reads them. `add` adds an address with a weekly or monthly schedule, `update` changes the schedule or switches a recipient off and on, `delete` removes one. Every action answers with the full list afterwards.\nOwner only: the key must belong to the workspace owner.\n\nChanging frequency: On `update` the day is checked against the frequency that results: switching a weekly recipient on day 5 to `monthly` keeps day 5; switching a monthly recipient on day 20 to `weekly` needs a `day` of 1 to 7 in the same call.\n\nSame list as workspace_details: `recipients` is the `client_report_emails` list of `/api/workspace_details`, with the plain `id` needed here.",
                "operationId": "workspace_report_emails",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "`list`, `add`, `update` or `delete`. Case does not matter.",
                                        "enum": [
                                            "list",
                                            "add",
                                            "update",
                                            "delete"
                                        ],
                                        "default": "list",
                                        "example": "add"
                                    },
                                    "email": {
                                        "type": "string",
                                        "format": "email",
                                        "description": "Required when `action` is `add`: the address to add.",
                                        "example": "report@example.com"
                                    },
                                    "report_id": {
                                        "type": "integer",
                                        "description": "Required when `action` is `update` or `delete`: plain recipient id from `recipients[].id`.",
                                        "example": 31
                                    },
                                    "frequency": {
                                        "type": "string",
                                        "description": "With `add` or `update`: `weekly` or `monthly`. Defaults to `weekly` on add and to the current value on update.",
                                        "enum": [
                                            "weekly",
                                            "monthly"
                                        ],
                                        "example": "weekly"
                                    },
                                    "day": {
                                        "type": "integer",
                                        "description": "With `add` or `update`: the day the report goes out, 1 (Monday) to 7 (Sunday) for weekly, 1 to 28 for monthly. Defaults to 1 on add and to the current value on update.",
                                        "example": 1
                                    },
                                    "active": {
                                        "type": "boolean",
                                        "description": "With `update`: `false` switches the report off for this recipient, `true` switches it back on. Left out, the current state is kept.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success` on list, `Recipient added.`, `Recipient updated.` or `Recipient removed.`"
                                        },
                                        "recipients": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain recipient id, the `report_id` of update and delete."
                                                    },
                                                    "email": {
                                                        "type": "string",
                                                        "format": "email",
                                                        "description": "Address that receives the report."
                                                    },
                                                    "frequency": {
                                                        "type": "string",
                                                        "description": "`weekly` or `monthly`."
                                                    },
                                                    "day": {
                                                        "type": "integer",
                                                        "description": "Weekday 1 (Monday) to 7 (Sunday) for weekly, day of month for monthly."
                                                    },
                                                    "active": {
                                                        "type": "boolean",
                                                        "description": "`false` when the report is switched off for this recipient."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Recipient added.",
                                    "recipients": [
                                        {
                                            "id": 31,
                                            "email": "report@example.com",
                                            "frequency": "weekly",
                                            "day": 1,
                                            "active": true
                                        },
                                        {
                                            "id": 28,
                                            "email": "cfo@example.com",
                                            "frequency": "monthly",
                                            "day": 1,
                                            "active": false
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\naction must be list, add, update or delete. (action is another word.)\n\nemail must be a valid email address. (action is add and email is missing or not an address.)\n\nfrequency must be weekly or monthly. (frequency is another word.)\n\nday must be 1 (Monday) to 7 (Sunday) for a weekly report. (A weekly schedule with a day outside 1 to 7.)\n\nday must be 1 to 28 for a monthly report. (A monthly schedule with a day outside 1 to 28.)\n\nSomething went wrong (The app refused the change; its own text is relayed when it sent one, for example `Please check your requested data!`)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can manage client report recipients. (The workspace belongs to someone else.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nreport_id is not a recipient of this workspace; see action list. (action is update or delete and report_id is missing or belongs to another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/roles": {
            "post": {
                "tags": [
                    "Team Roles"
                ],
                "summary": "List the account's roles with the permission and notification keys, or read one role in full.",
                "description": "Without `role_id` lists every role of the account together with `permission_keys` (every key `/api/role_manage` accepts in `permissions`) and `notification_keys` (every key it accepts as `notification_key`). With `role_id` returns that one role with the permissions it holds, its notification settings and the workflow stages it reviews.\nOwner only: the key must belong to the account owner. Role and user ids in this module are plain integers.\n\nFeature masters: `social`, `library`, `inbox`, `reports`, `dm`, `ads` and `client` are master keys that switch a whole feature on for the role; the keys that follow each one in the list are its finer permissions and only count while the master is held.\n\nReading as a member: A team member's own role in a workspace is on `members[].role` of `/api/workspace_members`; this endpoint is for the owner's account.",
                "operationId": "roles",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "role_id": {
                                        "type": "integer",
                                        "description": "Plain role id to read in full. Omit for the list.",
                                        "example": 5
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. Roles are account-wide; the workspace only decides whose roles are read, and it must be yours.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "roles": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain role id. List only."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Role name."
                                                    },
                                                    "description": {
                                                        "type": "string",
                                                        "description": "Role description, may be empty."
                                                    },
                                                    "template": {
                                                        "type": "string",
                                                        "description": "The template the role was made from: `contributor`, `writer`, `editor`, `publisher` or empty."
                                                    },
                                                    "is_template": {
                                                        "type": "boolean",
                                                        "description": "`true` for the four stock roles RecurPost seeds."
                                                    },
                                                    "members": {
                                                        "type": "integer",
                                                        "description": "How many workspace memberships across the account use this role."
                                                    }
                                                }
                                            }
                                        },
                                        "permission_keys": {
                                            "type": "array",
                                            "items": {
                                                "type": "string",
                                                "description": "Every permission key, feature masters included: `create-posts`, `edit-others`, `delete-own`, `delete-others`, `approve`, `publish`, `social`, `connect-accounts`, `disconnect-accounts`, `manage-accounts`, `library`, `lib-upload`, `lib-manage`, `lib-delete`, `inbox`, `inbox-reply`, `inbox-assign`, `reports`, `reports-export`, `dm`, `dm-create`, `dm-edit`, `ads`, `ads-create`, `client`, `send-client`, `approve-on-behalf`, `workspace-settings`, `invite`, `remove-members`. List only."
                                            }
                                        },
                                        "notification_keys": {
                                            "type": "array",
                                            "items": {
                                                "type": "string",
                                                "description": "Every notification key: `assigned`, `review`, `approved`, `changes`, `sla`, `client`, `urgent`, `pub-ok`, `pub-fail`, `reconnect`, `paused-queue`, `daily-sched`, `daily-sched-empty`, `post-summary`, `weekly`, `inbox-summary`, `digest`, `product-news`. List only."
                                            }
                                        },
                                        "role": {
                                            "type": "object",
                                            "description": "With `role_id`: the role with the same fields as a list item plus the three below.",
                                            "properties": {
                                                "permissions": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string",
                                                        "description": "The permission keys the role holds."
                                                    }
                                                },
                                                "notifications": {
                                                    "type": "object",
                                                    "description": "Notification key to `{email, mobile}` booleans. Keys never set are absent."
                                                },
                                                "workflow_stages": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string",
                                                        "description": "Names of the workflow stages this role reviews; a role on a stage cannot be deleted."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "roles": [
                                        {
                                            "id": 4,
                                            "name": "Publisher",
                                            "description": "Schedules and publishes",
                                            "template": "publisher",
                                            "is_template": true,
                                            "members": 3
                                        },
                                        {
                                            "id": 5,
                                            "name": "Editor",
                                            "description": "",
                                            "template": "editor",
                                            "is_template": false,
                                            "members": 1
                                        }
                                    ],
                                    "permission_keys": [
                                        "create-posts",
                                        "edit-others",
                                        "delete-own",
                                        "delete-others",
                                        "approve",
                                        "publish",
                                        "social",
                                        "connect-accounts",
                                        "disconnect-accounts",
                                        "manage-accounts",
                                        "library",
                                        "lib-upload",
                                        "lib-manage",
                                        "lib-delete",
                                        "inbox",
                                        "inbox-reply",
                                        "inbox-assign",
                                        "reports",
                                        "reports-export",
                                        "dm",
                                        "dm-create",
                                        "dm-edit",
                                        "ads",
                                        "ads-create",
                                        "client",
                                        "send-client",
                                        "approve-on-behalf",
                                        "workspace-settings",
                                        "invite",
                                        "remove-members"
                                    ],
                                    "notification_keys": [
                                        "assigned",
                                        "review",
                                        "approved",
                                        "changes",
                                        "sla",
                                        "client",
                                        "urgent",
                                        "pub-ok",
                                        "pub-fail",
                                        "reconnect",
                                        "paused-queue",
                                        "daily-sched",
                                        "daily-sched-empty",
                                        "post-summary",
                                        "weekly",
                                        "inbox-summary",
                                        "digest",
                                        "product-news"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nSomething went wrong (The app could not read the roles; its own text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can manage roles. (The workspace, and so the account, belongs to someone else.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nrole_id is not one of this account's roles. (role_id names no role of the account.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/role_manage": {
            "post": {
                "tags": [
                    "Team Roles"
                ],
                "summary": "Create, rename, duplicate or delete a role, or set its permissions and notifications.",
                "description": "One endpoint for every change to a role, chosen with `action`:\n- `create`: a new role named `name`, optionally starting from a `template`.\n- `rename`: gives `role_id` the new `name`.\n- `duplicate`: copies `role_id` with its permissions and notifications.\n- `set_permissions`: replaces the role's permission keys with `permissions`; keys not in the list are taken away.\n- `set_notification`: sets the `email` and `mobile` switches of one `notification_key`.\n- `delete`: removes the role with `confirm=true`; refused while members hold it or a workflow stage uses it.\n\nEvery action but `delete` answers with the role as `/api/roles` returns it with `role_id`. Owner only.\n\nset_permissions replaces, it does not add: Send the whole list the role should end up with. Read the current `permissions` with `/api/roles`, change it, send it back. A finer key without its feature master (for example `lib-upload` without `library`) is stored but has no effect.\n\nStock roles: The four seeded roles (`is_template` true) can be renamed and changed like any other; deleting one is refused only while it is in use.",
                "operationId": "role_manage",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "`create`, `rename`, `duplicate`, `set_permissions`, `set_notification` or `delete`. Case does not matter.",
                                        "enum": [
                                            "create",
                                            "rename",
                                            "duplicate",
                                            "set_permissions",
                                            "set_notification",
                                            "delete"
                                        ],
                                        "example": "create"
                                    },
                                    "role_id": {
                                        "type": "integer",
                                        "description": "Required for every action except `create`: plain role id from `/api/roles`.",
                                        "example": 5
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "Required when `action` is `create` or `rename`: the role name, 1 to 40 characters. Surrounding spaces are trimmed.",
                                        "example": "Reviewer"
                                    },
                                    "template": {
                                        "type": "string",
                                        "description": "With `create`: start from a stock template, `contributor`, `writer`, `editor` or `publisher`. Case does not matter. Omit for an empty role.",
                                        "enum": [
                                            "contributor",
                                            "writer",
                                            "editor",
                                            "publisher"
                                        ],
                                        "example": "editor"
                                    },
                                    "permissions": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Required when `action` is `set_permissions`: the full list of permission keys the role should hold, as an array or a comma-separated string, from `permission_keys` of `/api/roles`. Duplicates are dropped; an empty list takes every permission away.",
                                        "example": [
                                            "create-posts",
                                            "edit-others",
                                            "social"
                                        ]
                                    },
                                    "notification_key": {
                                        "type": "string",
                                        "description": "Required when `action` is `set_notification`: one of `notification_keys` of `/api/roles`.",
                                        "example": "assigned"
                                    },
                                    "email": {
                                        "type": "boolean",
                                        "description": "With `set_notification`: whether members with this role get the email. Defaults to `false` when left out.",
                                        "example": true
                                    },
                                    "mobile": {
                                        "type": "boolean",
                                        "description": "With `set_notification`: whether they get the mobile push. Defaults to `false` when left out.",
                                        "example": false
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Required when `action` is `delete`: must be `true`.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. Roles are account-wide; the workspace must be yours.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "action"
                                ],
                                "example": {
                                    "action": "create"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "The app's confirmation: `Role created.`, `Role renamed.`, `Role duplicated.`, `Permissions saved.`, `Notification saved.` or `\"Reviewer\" deleted.` with the role's name."
                                        },
                                        "role": {
                                            "type": "object",
                                            "description": "The role after the change, in the single-role shape of `/api/roles` (`id, name, description, template, is_template, members, permissions, notifications, workflow_stages`). Absent after `delete`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Role created.",
                                    "role": {
                                        "id": 9,
                                        "name": "Reviewer",
                                        "description": "",
                                        "template": "editor",
                                        "is_template": false,
                                        "members": 0,
                                        "permissions": [
                                            "create-posts",
                                            "edit-others",
                                            "approve",
                                            "library",
                                            "lib-upload"
                                        ],
                                        "notifications": {
                                            "assigned": {
                                                "email": true,
                                                "mobile": false
                                            }
                                        },
                                        "workflow_stages": []
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\naction must be one of create, rename, duplicate, set_permissions, set_notification, delete. (action is missing or another word.)\n\nname must be 1 to 40 characters. (create or rename with a blank or too long name.)\n\ntemplate must be one of contributor, writer, editor, publisher. (create with another template.)\n\nUnknown permission keys: fly. See the permission_keys of the roles call. (set_permissions with a key that is not in permission_keys; the message lists the unknown ones.)\n\nnotification_key must be one of assigned, review, approved, changes, sla, client, urgent, pub-ok, pub-fail, reconnect, paused-queue, daily-sched, daily-sched-empty, post-summary, weekly, inbox-summary, digest, product-news. (set_notification with a key that is not in notification_keys.)\n\nSend confirm=true to delete the role. (delete without confirm=true.)\n\nSomething went wrong (The app refused the change; its own text is relayed when it sent one, for example `Failed to create role.`)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can manage roles. (The workspace, and so the account, belongs to someone else.)\n\nThere are 2 member(s) under this role. Reassign them to another role first, then delete this role. (delete while members still hold the role; the number is the member count.)\n\nThis role still reviews Review in your workflow. Remove it from those stages in the Workflow Builder first, then delete this role. (delete while a workflow stage uses the role; the message lists the stage names.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nrole_id is not one of this account's roles. (Any action but create, and role_id is missing or names no role of the account.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/social_account_list": {
            "post": {
                "tags": [
                    "Social Accounts"
                ],
                "summary": "List the social accounts of a workspace with their connection state.",
                "description": "Returns every social account in the workspace, paused ones included. The `smpa_id` values are the account ids you pass as `account_id` to `/api/post_content`, `/api/history_data` and the other endpoints that target an account.\nAn account whose token expired comes back as `Needs Reconnection` together with a `reconnect_url` you can hand to the account owner. Use `/api/social_account_details` for the full state of one account.\n\nOnly two states: This list tells connected and expired apart, nothing more. For `active` / `paused` / `needs_reconnection`, the network key, groups and workspaces of one account call `/api/social_account_details`.\n\nLegacy endpoint: with body or Basic credentials errors arrive as HTTP 200 with the real status in the body field `status`. With a Bearer token it returns real HTTP status codes.",
                "operationId": "social_account_list",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "social_accounts": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "smpa_id": {
                                                        "type": "string",
                                                        "description": "Encrypted account id. Pass it as `account_id` (or `id`) to the other endpoints."
                                                    },
                                                    "smpa_name": {
                                                        "type": "string",
                                                        "description": "Account name followed by the network type in brackets, e.g. `My Page (Facebook Page)`."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "`Connected`, or `Needs Reconnection` when the token expired. A paused account still reads `Connected`."
                                                    },
                                                    "reconnect_url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Link that lets the account holder reconnect the account without logging in to RecurPost."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "social_accounts": [
                                        {
                                            "smpa_id": "aB3dE5fG==",
                                            "smpa_name": "My Page (Facebook Page)",
                                            "status": "Connected",
                                            "reconnect_url": "https://social.recurpost.com/reconnect/aB3dE5fG"
                                        },
                                        {
                                            "smpa_id": "hJ7kL9mN==",
                                            "smpa_name": "Bird (X (Twitter) Profile)",
                                            "status": "Needs Reconnection",
                                            "reconnect_url": "https://social.recurpost.com/reconnect/hJ7kL9mN"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nWe can't find any social account (The workspace has no social account yet.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/connect_social_account_urls": {
            "post": {
                "tags": [
                    "Social Accounts"
                ],
                "summary": "Get the links that connect a new social account to a workspace.",
                "description": "Returns one connect link per supported network type. Open a link in a browser (or send it to the account holder) to run the network's login and add the account to the workspace; no RecurPost login is needed. Instagram Business comes twice: once through Facebook Login and once through Instagram's own Direct Login.\n\nLinks are personal: Each link is bound to your user, the workspace and the workspace owner. Whoever opens it adds the account to that workspace under the owner's plan, so share links only with people who should connect accounts there.\n\nLegacy endpoint: with body or Basic credentials errors arrive as HTTP 200 with the real status in the body field `status`. With a Bearer token it returns real HTTP status codes.",
                "operationId": "connect_social_account_urls",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. The new account lands in this workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "social_links": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "platform_name": {
                                                        "type": "string",
                                                        "description": "Network and account type, e.g. `Facebook Page`, `LinkedIn Company`, `Instagram Business Profile (Facebook Login)`, `Instagram Business Profile (Direct Login)`, `YouTube Channel`."
                                                    },
                                                    "connect_url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Link that starts the connection flow for that network."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "social_links": [
                                        {
                                            "platform_name": "Facebook Profile",
                                            "connect_url": "https://social.recurpost.com/connect/1/aB3dE5fG"
                                        },
                                        {
                                            "platform_name": "Facebook Page",
                                            "connect_url": "https://social.recurpost.com/connect/2/aB3dE5fG"
                                        },
                                        {
                                            "platform_name": "X (Twitter) Profile",
                                            "connect_url": "https://social.recurpost.com/connect/4/aB3dE5fG"
                                        },
                                        {
                                            "platform_name": "Instagram Business Profile (Facebook Login)",
                                            "connect_url": "https://social.recurpost.com/connect/12/aB3dE5fG"
                                        },
                                        {
                                            "platform_name": "Instagram Business Profile (Direct Login)",
                                            "connect_url": "https://social.recurpost.com/connect/12.1/aB3dE5fG"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nYou are not authorised to manage this workspace. (The app refuses the workspace for the caller.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/social_account_details": {
            "post": {
                "tags": [
                    "Social Accounts"
                ],
                "summary": "Read one social account: network, state, timezone, groups, workspaces and Meta permissions.",
                "description": "Returns the full record of one connected account. Tokens never leave the API. For Facebook, Instagram and Threads accounts `permissions` lists the scopes RecurPost asks the network for, which helps when a post fails with a permission error; for every other network it is an empty list.",
                "operationId": "social_account_details",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted account id from `/api/social_account_list`. Exactly one id.",
                                        "example": "aB3dE5fG=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. When sent, the account must be part of that workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": "aB3dE5fG=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "account": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted account id."
                                                },
                                                "network": {
                                                    "type": "string",
                                                    "description": "Network key: `facebook`, `twitter`, `linkedin`, `instagram`, `pinterest`, `google_my_business`, `tiktok`, `youtube`, `threads` or `bluesky`."
                                                },
                                                "network_type": {
                                                    "type": "string",
                                                    "description": "Network and account type as shown in RecurPost, e.g. `Facebook Page`, `LinkedIn Company`, `Pinterest Board`."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Account name on the network."
                                                },
                                                "username": {
                                                    "type": "string",
                                                    "description": "Handle or profile link slug on the network."
                                                },
                                                "image": {
                                                    "type": "string",
                                                    "format": "uri",
                                                    "description": "Profile picture URL."
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "`active`, `paused` or `needs_reconnection`."
                                                },
                                                "timezone": {
                                                    "type": "string",
                                                    "description": "Timezone of the account; post times for this account are shown in it."
                                                },
                                                "connected_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "description": "When the account was first connected, UTC."
                                                },
                                                "groups": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "description": "Encrypted group id (see `/api/account_group_list`)."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Group name."
                                                            }
                                                        }
                                                    }
                                                },
                                                "workspaces": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "description": "Encrypted id of a workspace of the owner that holds this account."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Workspace name."
                                                            }
                                                        }
                                                    }
                                                },
                                                "permissions": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string",
                                                        "description": "Meta permission scopes RecurPost needs on this account (Facebook profile, page, group, Instagram, Threads). Empty for other networks."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "account": {
                                        "id": "aB3dE5fG==",
                                        "network": "facebook",
                                        "network_type": "Facebook Page",
                                        "name": "My Page",
                                        "username": "mypage",
                                        "image": "https://graph.facebook.com/123/picture",
                                        "status": "active",
                                        "timezone": "America/New_York",
                                        "connected_at": "2026-03-04 09:12:45",
                                        "groups": [
                                            {
                                                "id": "gR1pQ2sT==",
                                                "name": "Brands"
                                            }
                                        ],
                                        "workspaces": [
                                            {
                                                "id": "nX2k9Qp7Lw==",
                                                "name": "Agency"
                                            }
                                        ],
                                        "permissions": [
                                            "pages_manage_engagement",
                                            "pages_manage_metadata",
                                            "pages_manage_posts",
                                            "pages_read_engagement",
                                            "pages_read_user_content",
                                            "read_insights",
                                            "pages_messaging",
                                            "pages_show_list",
                                            "business_management",
                                            "instagram_basic",
                                            "instagram_manage_messages",
                                            "pages_manage_ads",
                                            "ads_read",
                                            "ads_management"
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "A valid id is required. (id is missing, does not decrypt, or holds more than one id.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account is not in that workspace.)\n\nSocial account not found. (The account row no longer exists.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/social_account_status": {
            "post": {
                "tags": [
                    "Social Accounts"
                ],
                "summary": "Pause or reactivate one social account.",
                "description": "Pausing stops every scheduled and library post for the account without disconnecting it; reactivating resumes them. Reactivation runs the same plan checks as the app: it is refused when the owner is already at the account limit of the plan, when a free plan holds two accounts of the same kind, or when the same profile is active under another RecurPost account.\n\nPosts are not rescheduled: Pausing does not move queued posts; they stay in the queue and go out once the account is active again, provided their time has not passed. Check `/api/queue_list` after reactivating.",
                "operationId": "social_account_status",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted account id from `/api/social_account_list`.",
                                        "example": "aB3dE5fG=="
                                    },
                                    "status": {
                                        "type": "string",
                                        "description": "New state. Case does not matter.",
                                        "enum": [
                                            "active",
                                            "paused"
                                        ],
                                        "example": "paused"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. When sent, the account must be part of that workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id",
                                    "status"
                                ],
                                "example": {
                                    "id": "aB3dE5fG==",
                                    "status": "paused"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "The app's confirmation text, e.g. `Social account paused`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Social account paused"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "A valid id is required. (id is missing, does not decrypt, or holds more than one id.)\n\nstatus must be active or paused. (status is missing or another word.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nThe account status could not be changed. (The app answered without a usable status; any other app error text is relayed as is.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account does not belong to the workspace owner.)\n\nYour current plan allows you to manage N social profiles. You currently have M profiles. Please delete extra profiles and try again. (Reactivating would exceed the owner's plan limit.)\n\nThis social profile exists under another RecurPost account. Please upgrade to a paid plan or remove it from there to use it again. (Reactivating a profile that is active under another account.)\n\nOur free plan offers you one profile of a kind. You have more than one profiles of the same kind. Please delete extra profiles and try again. (Reactivating a duplicate kind on a free plan.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account is not in that workspace.)\n\nSocial account not found. (The app cannot find the account in the workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/social_account_rename": {
            "post": {
                "tags": [
                    "Social Accounts"
                ],
                "summary": "Rename a social account and, optionally, set its time zone or a new Bluesky app password.",
                "description": "Changes the name a social account is shown under in RecurPost (the name on the network is not touched). `timezone` sets the zone the account's post times are shown and counted in; when it is not sent the current zone is kept (the app's own call used to reset it to New York). `bluesky_password` stores a new app password on a Bluesky account and is ignored on every other network.\nIds are encrypted strings from `/api/social_account_list`.",
                "operationId": "social_account_rename",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted social account id from `/api/social_account_list`. Exactly one id.",
                                        "example": "aB3dE5fG=="
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "New display name, 1 to 100 characters after trimming.",
                                        "example": "Acme Facebook Page"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. When sent, the account must be part of that workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "timezone": {
                                        "type": "string",
                                        "description": "IANA zone name for the account, in any case; the canonical spelling is saved. Omit to keep the current zone.",
                                        "example": "Europe/Paris"
                                    },
                                    "bluesky_password": {
                                        "type": "string",
                                        "description": "New Bluesky app password; Bluesky accounts only, ignored elsewhere.",
                                        "example": "abcd-efgh-ijkl-mnop"
                                    }
                                },
                                "required": [
                                    "account_id",
                                    "name"
                                ],
                                "example": {
                                    "account_id": "aB3dE5fG==",
                                    "name": "Acme Facebook Page"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Account updated.`"
                                        },
                                        "account": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted account id."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "The name as saved."
                                                },
                                                "network": {
                                                    "type": "string",
                                                    "description": "Network key: `facebook`, `twitter`, `linkedin`, `instagram`, `pinterest`, `google_my_business`, `tiktok`, `youtube`, `threads` or `bluesky`."
                                                },
                                                "timezone": {
                                                    "type": "string",
                                                    "description": "The account's time zone after the call."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Account updated.",
                                    "account": {
                                        "id": "aB3dE5fG==",
                                        "name": "Acme Facebook Page",
                                        "network": "facebook",
                                        "timezone": "Europe/Paris"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "account_id is required. (account_id is missing, does not decrypt, or holds more than one id.)\n\nname must be 1 to 100 characters. (name is blank or longer than 100 characters.)\n\ntimezone must be an IANA zone name such as America/New_York. (timezone was sent and is not a name on the IANA list.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nNo Social Account Found. (The app could not find the account in the workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account does not belong to the workspace owner.)\n\nYou are not authorised to manage this workspace. (The app does not count you as a member of the workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account is not in that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/social_account_remove": {
            "post": {
                "tags": [
                    "Social Accounts"
                ],
                "summary": "Disconnect a social account and delete everything stored for it.",
                "description": "Disconnects a social account from RecurPost and deletes its queue and history, its schedules, its inbox, its DM automations and its workspace links. Library posts stay. Only the workspace owner's own key may use it, and the call must carry `confirm=true`; without it the 400 names the account and what would go. Ids are encrypted strings from `/api/social_account_list`.\nChecks run in this order: workspace, owner, account ownership, then `confirm`.\n\nNot reversible: Queued and published posts, schedules, inbox conversations and automations of the account are deleted for good. Reconnecting the account later starts from nothing. Pause it with `/api/social_account_status` when you only want it to stop posting.",
                "operationId": "social_account_remove",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted social account id from `/api/social_account_list`. Exactly one id.",
                                        "example": "aB3dE5fG=="
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be `true` (or `1`); the call refuses without it.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. When sent, the account must be part of that workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "account_id",
                                    "confirm"
                                ],
                                "example": {
                                    "account_id": "aB3dE5fG==",
                                    "confirm": true
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`<account name> removed.`"
                                        },
                                        "accounts_left": {
                                            "type": "integer",
                                            "description": "Social accounts the owner still has connected."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "My Page removed.",
                                    "accounts_left": 3
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\naccount_id is required. (account_id is missing, does not decrypt, or holds more than one id.)\n\nSend confirm=true to remove <account name> with its queue, history, schedules and inbox. (confirm is missing or not true.)\n\nSomething Went Wrong. Please Try Again. (The app could not delete the account.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can remove a social account. (The key belongs to a team member, not the workspace owner.)\n\nSorry, there was an issue. Please try again later or contact support. (The account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account is not in that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/tiktok_options": {
            "post": {
                "tags": [
                    "Social Accounts"
                ],
                "summary": "Privacy levels a TikTok post can be published with.",
                "description": "Returns the privacy options `/api/post_content` accepts for TikTok. Send the `value` as the TikTok privacy setting; `name` and `description` are the labels TikTok shows for it.",
                "operationId": "tiktok_options",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": []
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "privacy_options": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "value": {
                                                        "type": "string",
                                                        "description": "Value to send when posting: `PUBLIC_TO_EVERYONE`, `MUTUAL_FOLLOW_FRIENDS` or `SELF_ONLY`."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Short label."
                                                    },
                                                    "description": {
                                                        "type": "string",
                                                        "description": "Who can watch."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "privacy_options": [
                                        {
                                            "value": "PUBLIC_TO_EVERYONE",
                                            "name": "Public",
                                            "description": "Everyone can watch"
                                        },
                                        {
                                            "value": "MUTUAL_FOLLOW_FRIENDS",
                                            "name": "Friends",
                                            "description": "Mutual followers only"
                                        },
                                        {
                                            "value": "SELF_ONLY",
                                            "name": "Self Only",
                                            "description": "Only you can see"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/youtube_options": {
            "post": {
                "tags": [
                    "Social Accounts"
                ],
                "summary": "Categories and languages for YouTube posts, plus the playlists of one channel.",
                "description": "Returns the video categories and the default languages `/api/post_content` accepts for YouTube. Pass the encrypted id of a YouTube account in `id` to also get its playlists; that part asks YouTube live, so an expired token answers 409. Without `id` the call reads nothing from YouTube and `playlists` is left out.\n\nStatic lists, live playlists: Categories and languages are fixed lists; cache them. Playlists are fetched from YouTube on every call (all pages, 50 per page), so avoid calling with `id` in a tight loop.",
                "operationId": "youtube_options",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted account id of a YouTube channel from `/api/social_account_list`. Adds `playlists` to the response.",
                                        "example": "yT4uV5wX=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. Only read when `id` is sent; the channel must then be part of that workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "categories": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "YouTube category id to send when posting, e.g. `22` for People & Blogs."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Category name."
                                                    }
                                                }
                                            }
                                        },
                                        "languages": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "code": {
                                                        "type": "string",
                                                        "description": "BCP-47 language code to send as the default video or audio language."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Language name."
                                                    }
                                                }
                                            }
                                        },
                                        "playlists": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "YouTube playlist id. Present only when `id` was sent."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Playlist title."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "categories": [
                                        {
                                            "id": 1,
                                            "name": "Film & Animation"
                                        },
                                        {
                                            "id": 22,
                                            "name": "People & Blogs"
                                        },
                                        {
                                            "id": 27,
                                            "name": "Education"
                                        }
                                    ],
                                    "languages": [
                                        {
                                            "code": "en",
                                            "name": "English"
                                        },
                                        {
                                            "code": "es",
                                            "name": "Spanish"
                                        }
                                    ],
                                    "playlists": [
                                        {
                                            "id": "PLx9Qp7LwAb3dE5fG",
                                            "title": "Product updates"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "A valid id is required. (id is sent but does not decrypt, or holds more than one id.)\n\nInvalid workspace_id. (id and workspace_id are sent and workspace_id does not decrypt to an id.)\n\nid must be a YouTube account. (The account is on another network.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account is not in that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "YouTube did not return the playlists. Reconnect the account and try again. (The channel token is expired or YouTube refused the request.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/facebook_backgrounds": {
            "post": {
                "tags": [
                    "Social Accounts"
                ],
                "summary": "The text-post backgrounds Facebook offers, by category.",
                "description": "Lists the coloured and patterned backgrounds Facebook offers for text-only page posts, grouped by category, with each background's id, text colour, full image and thumbnail. Any member of the workspace may read it; the list is the same for every account. Background ids are plain strings as Facebook names them; send one as `fb_background_id` on `/api/post_content`, `/api/library_content_update` or `/api/queue_post_update` for a post without media.",
                "operationId": "facebook_backgrounds",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "categories": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Category name."
                                                    },
                                                    "backgrounds": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "object",
                                                            "properties": {
                                                                "id": {
                                                                    "type": "string",
                                                                    "description": "Facebook's background id."
                                                                },
                                                                "text_color": {
                                                                    "type": "string",
                                                                    "description": "Text colour used on this background, as a CSS colour."
                                                                },
                                                                "image_url": {
                                                                    "type": "string",
                                                                    "format": "uri",
                                                                    "description": "Full-size background image."
                                                                },
                                                                "thumbnail_url": {
                                                                    "type": "string",
                                                                    "format": "uri",
                                                                    "description": "Thumbnail of the background."
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "categories": [
                                        {
                                            "name": "Solid",
                                            "backgrounds": [
                                                {
                                                    "id": "12",
                                                    "text_color": "#ffffff",
                                                    "image_url": "https://static.xx.fbcdn.net/backgrounds/12_background.png",
                                                    "thumbnail_url": "https://static.xx.fbcdn.net/backgrounds/12_thumbnail.png"
                                                }
                                            ]
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/mention_search": {
            "post": {
                "tags": [
                    "Social Accounts"
                ],
                "summary": "Find Facebook pages or LinkedIn organisations to mention in a post.",
                "description": "Searches the network for pages and organisations matching `query`, using the connected accounts of the workspace (or only `account_ids`) to run the search. For `facebook` the result's `id` is a page id: put it in `fb_mentions` on `/api/post_content` and write `@<page id>` in the text where the mention should appear. LinkedIn results come from the same app call and are listed for reference; `/api/post_content` has no LinkedIn mention field yet.\nNo match answers 200 with an empty `mentions` list. `account_ids` are encrypted strings from `/api/social_account_list`.",
                "operationId": "mention_search",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "network": {
                                        "type": "string",
                                        "description": "`facebook` or `linkedin`, in any case.",
                                        "enum": [
                                            "facebook",
                                            "linkedin"
                                        ],
                                        "example": "facebook"
                                    },
                                    "query": {
                                        "type": "string",
                                        "description": "Name or part of a name to search for.",
                                        "example": "acme"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "account_ids": {
                                        "type": "string",
                                        "description": "Encrypted social account ids to search with; one id, a comma-separated list or an array. Every id must be an account of the workspace owner (and in the workspace when `workspace_id` is sent). Defaults to every connected account of the network.",
                                        "example": "aB3dE5fG=="
                                    }
                                },
                                "required": [
                                    "network",
                                    "query"
                                ],
                                "example": {
                                    "network": "facebook",
                                    "query": "acme"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "mentions": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Page or organisation id on the network; for Facebook the value for `fb_mentions`."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Display name."
                                                    },
                                                    "original_name": {
                                                        "type": "string",
                                                        "description": "Name as the network returned it."
                                                    },
                                                    "tag": {
                                                        "type": "string",
                                                        "description": "The tag the composer inserts; for Facebook the page id again."
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "description": "Kind of result, usually `page`."
                                                    },
                                                    "headline": {
                                                        "type": "string",
                                                        "description": "Headline or tagline when the network gives one, else empty."
                                                    },
                                                    "image_url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Profile picture; may be empty."
                                                    },
                                                    "profile_url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Link to the page on the network; may be empty."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "mentions": [
                                        {
                                            "id": "104857362001",
                                            "name": "Acme",
                                            "original_name": "Acme Inc",
                                            "tag": "104857362001",
                                            "type": "page",
                                            "headline": "",
                                            "image_url": "https://graph.facebook.com/104857362001/picture",
                                            "profile_url": "https://www.facebook.com/acme"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "network (facebook or linkedin) and query are required. (network is not facebook or linkedin, or query is blank.)\n\naccount_ids holds an invalid id. (An account id does not decrypt.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\n<the network's refusal> (The network refused the search for the one account used; its message is relayed.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (An account in account_ids does not belong to the workspace owner.)\n\nPlease connect at least one Facebook account to search mentions! (No account of the network is connected (LinkedIn names LinkedIn). The re-connect form, Please re-connect at least one of the existing Facebook accounts to search mentions!, means every account of the network needs reconnecting.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and an account in account_ids is not in that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/instagram_products": {
            "post": {
                "tags": [
                    "Social Accounts"
                ],
                "summary": "Catalogs of an Instagram business account, or the products in one catalog, for product tags.",
                "description": "Without `catalog_id` lists the product catalogs the Instagram business account can tag from; with it lists the products of that catalog, searchable with `query` and paged with the `after` cursor Meta returns. Product ids go into `in_product_tags` (feed images) and `in_reel_product_tags` (reels) on `/api/post_content`, together with this `account_id`.\n`account_id` is an encrypted string from `/api/social_account_list`; `catalog_id` and product ids are Meta's own numeric strings.\n\nFacebook login and catalog access: Product tagging needs an Instagram business account connected through Facebook login with the catalog assigned to the Facebook user in Meta Commerce Manager. An account without that answers the 400 with Meta's reconnect or permission text.",
                "operationId": "instagram_products",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the Instagram business account. Exactly one id.",
                                        "example": "Qm7Zt3Vb1A=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. When sent, the account must be part of that workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "catalog_id": {
                                        "type": "string",
                                        "description": "A catalog id from the catalog list of this call; switches the answer to that catalog's products.",
                                        "example": "900123456789"
                                    },
                                    "query": {
                                        "type": "string",
                                        "description": "Text to filter the products by name; only with `catalog_id`.",
                                        "example": "mug"
                                    },
                                    "after": {
                                        "type": "string",
                                        "description": "The `next_cursor` of the previous page; only with `catalog_id`.",
                                        "example": "QVFIUmxZ..."
                                    }
                                },
                                "required": [
                                    "account_id"
                                ],
                                "example": {
                                    "account_id": "Qm7Zt3Vb1A=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "catalogs": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Catalog id (without `catalog_id`)."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Catalog name."
                                                    },
                                                    "shop": {
                                                        "type": "string",
                                                        "description": "Shop the catalog is linked to, or empty."
                                                    },
                                                    "business": {
                                                        "type": "string",
                                                        "description": "Business that owns the catalog, or empty."
                                                    },
                                                    "products": {
                                                        "type": "integer",
                                                        "description": "Products in the catalog."
                                                    },
                                                    "linked_to_shop": {
                                                        "type": "boolean",
                                                        "description": "`true` for the catalog of the account's Instagram shop; linked catalogs are listed first."
                                                    }
                                                }
                                            }
                                        },
                                        "products": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Product id for `in_product_tags` and `in_reel_product_tags` (with `catalog_id`)."
                                                    },
                                                    "retailer_id": {
                                                        "type": "string",
                                                        "description": "Your own SKU or id from the catalog feed."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Product name."
                                                    },
                                                    "description": {
                                                        "type": "string",
                                                        "description": "Product description, when Meta returned one."
                                                    },
                                                    "price": {
                                                        "type": "string",
                                                        "description": "Price as Meta formats it."
                                                    },
                                                    "currency": {
                                                        "type": "string",
                                                        "description": "Currency code."
                                                    },
                                                    "availability": {
                                                        "type": "string",
                                                        "description": "Meta availability value, for example `in stock`."
                                                    },
                                                    "condition": {
                                                        "type": "string",
                                                        "description": "Meta condition value, for example `new`."
                                                    },
                                                    "image_url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Product image."
                                                    },
                                                    "url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Product page."
                                                    },
                                                    "brand": {
                                                        "type": "string",
                                                        "description": "Brand, when set."
                                                    },
                                                    "review_status": {
                                                        "type": "string",
                                                        "description": "Meta's review status of the product."
                                                    }
                                                }
                                            }
                                        },
                                        "next_cursor": {
                                            "type": "string",
                                            "description": "Cursor for the next page of products; empty on the last page (with `catalog_id`)."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "products": [
                                        {
                                            "id": "6612345678901",
                                            "retailer_id": "MUG-001",
                                            "name": "Planner Mug",
                                            "description": "A mug for long planning sessions.",
                                            "price": "9.00",
                                            "currency": "USD",
                                            "availability": "in stock",
                                            "condition": "new",
                                            "image_url": "https://example.com/img/mug.jpg",
                                            "url": "https://example.com/shop/mug",
                                            "brand": "Acme",
                                            "review_status": "approved"
                                        }
                                    ],
                                    "next_cursor": ""
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\naccount_id is required. (account_id is missing, does not decrypt, or holds more than one id.)\n\ncatalog_id must be a catalog id from this call. (catalog_id is not a numeric string.)\n\nWe couldn't load the catalogs for this profile. (Meta refused the catalog list (the products form says We couldn't load the products in this catalog.). A Meta permission or token error replaces the text with a reconnect hint.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account does not belong to the workspace owner.)\n\nYou don't have access to this workspace. (The app does not count you as a member of the workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account is not in that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This profile needs to be reconnected. Please visit the Social Profiles page to reconnect it. (The account's Instagram token is dead; the body also carries `reconnect_required: true`.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/instagram_audio_search": {
            "post": {
                "tags": [
                    "Social Accounts"
                ],
                "summary": "Search Instagram's music library for a reel, or read one track by id.",
                "description": "Searches the music and original sounds Instagram offers for reels on an Instagram business account connected through Facebook login. Send `query` and `audio_type` to search, or `audio_id` to read one track. The result's `id` goes into `in_audio_id` on `/api/post_content` together with this call's `account_id` as `in_audio_account_id`; `title`, `artist` and `duration_ms` fill `in_audio_title`, `in_audio_artist` and `in_audio_duration_ms`.\n`account_id` is an encrypted string from `/api/social_account_list`; audio ids are Instagram's own strings.",
                "operationId": "instagram_audio_search",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the Instagram business account the reel will go to. Exactly one id.",
                                        "example": "Qm7Zt3Vb1A=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. When sent, the account must be part of that workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "query": {
                                        "type": "string",
                                        "description": "Title, artist or words to search for. Ignored when `audio_id` is sent.",
                                        "example": "summer"
                                    },
                                    "audio_type": {
                                        "type": "string",
                                        "description": "`music` for licensed tracks or `original_sound` for creator sounds.",
                                        "enum": [
                                            "music",
                                            "original_sound"
                                        ],
                                        "default": "music",
                                        "example": "music"
                                    },
                                    "audio_id": {
                                        "type": "string",
                                        "description": "An audio id from an earlier search; reads that one track instead of searching.",
                                        "example": "1012345678901234"
                                    }
                                },
                                "required": [
                                    "account_id"
                                ],
                                "example": {
                                    "account_id": "Qm7Zt3Vb1A=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "account_id": {
                                            "type": "string",
                                            "description": "The encrypted account id the search ran for; send it as `in_audio_account_id`."
                                        },
                                        "tracks": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Audio id for `in_audio_id`."
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "description": "`music` or `original_sound`."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Track title."
                                                    },
                                                    "artist": {
                                                        "type": "string",
                                                        "description": "Artist or creator."
                                                    },
                                                    "duration_ms": {
                                                        "type": "integer",
                                                        "description": "Length in milliseconds; 0 when unknown."
                                                    },
                                                    "cover_url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Cover art; may be empty."
                                                    },
                                                    "preview_url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Audio preview; may be empty."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "account_id": "Qm7Zt3Vb1A==",
                                    "tracks": [
                                        {
                                            "id": "1012345678901234",
                                            "type": "music",
                                            "title": "Summer Days",
                                            "artist": "The Planners",
                                            "duration_ms": 30000,
                                            "cover_url": "https://scontent.cdninstagram.com/covers/summer.jpg",
                                            "preview_url": "https://scontent.cdninstagram.com/audio/summer.m4a"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\naccount_id is required. (account_id is missing, does not decrypt, or holds more than one id.)\n\naudio_type must be music or original_sound. (audio_type is another value.)\n\n<Meta's error message> (Instagram refused the search or the id was not found (`not_found`); the message is relayed.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account is not in that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This account must be connected through Facebook login, and be connected, to pick music. (The account was connected with Instagram's direct login, or its token has expired; the body also carries `reconnect_required: true`.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/click_tracking": {
            "post": {
                "tags": [
                    "Social Accounts"
                ],
                "summary": "Turn link click tracking on or off for one social account.",
                "description": "Switches RecurPost's link click tracking for one social account: when it is on, links in that account's posts are rewritten through the tracking shortener so clicks appear in reports. Only the workspace owner's own key may change it. `account_id` is an encrypted string from `/api/social_account_list`.",
                "operationId": "click_tracking",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted social account id. Exactly one id.",
                                        "example": "aB3dE5fG=="
                                    },
                                    "enabled": {
                                        "type": "boolean",
                                        "description": "`true`, `1`, `yes` or `on` turns tracking on; any other value turns it off.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. When sent, the account must be part of that workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "account_id",
                                    "enabled"
                                ],
                                "example": {
                                    "account_id": "aB3dE5fG==",
                                    "enabled": true
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Click tracking enabled.` or `Click tracking disabled.`"
                                        },
                                        "account_id": {
                                            "type": "string",
                                            "description": "Encrypted account id."
                                        },
                                        "enabled": {
                                            "type": "boolean",
                                            "description": "The state after the call."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Click tracking enabled.",
                                    "account_id": "aB3dE5fG==",
                                    "enabled": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\naccount_id is required. (account_id is missing, does not decrypt, or holds more than one id.)\n\nenabled is required. (enabled was not sent.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can change click tracking. (The key belongs to a team member, not the workspace owner.)\n\nSorry, there was an issue. Please try again later or contact support. (The account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account is not in that workspace.)\n\nError while updating click tracking status. (The app could not write the switch.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/share_connect_link": {
            "post": {
                "tags": [
                    "Social Accounts"
                ],
                "summary": "Email clients a link that connects their social accounts into this workspace.",
                "description": "Sends up to 10 people an email with a link that lets them connect their own social accounts into the workspace without a RecurPost login, one tile per network in `networks`. Any member of the workspace may send it. The emails go out during the call.\n`networks` takes these keys: `facebook_profile`, `facebook_page`, `facebook_group`, `twitter`, `linkedin_profile`, `linkedin_page`, `pinterest`, `google_business`, `instagram` (through Facebook login), `instagram_direct` (Instagram's own login), `tiktok`, `youtube`, `threads`, `bluesky`. For a link you open yourself use `/api/connect_social_account_urls`.",
                "operationId": "share_connect_link",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "emails": {
                                        "type": "array",
                                        "items": [],
                                        "description": "1 to 10 addresses, as an array or a comma-separated string; duplicates are dropped.",
                                        "example": [
                                            "client@example.com"
                                        ]
                                    },
                                    "networks": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Network keys from the list above, as an array or a comma-separated string, in any case. At least one.",
                                        "example": [
                                            "facebook_page",
                                            "instagram"
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. The connected accounts land in this workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "emails",
                                    "networks"
                                ],
                                "example": {
                                    "emails": [
                                        "client@example.com"
                                    ],
                                    "networks": [
                                        "facebook_page",
                                        "instagram"
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Invite sent.` for one address, `Invites sent.` for several."
                                        },
                                        "emails": {
                                            "type": "array",
                                            "items": {
                                                "type": "string",
                                                "format": "email",
                                                "description": "The addresses the invitation went to, duplicates removed."
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Invites sent.",
                                    "emails": [
                                        "client@example.com",
                                        "owner@example.com"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nemails must hold 1 to 10 addresses. (No address, or more than 10 distinct ones.)\n\nPlease check this email address: <address> (An address does not parse.)\n\nnetworks holds an unknown network: <value>. Use facebook_profile, facebook_page, facebook_group, twitter, linkedin_profile, linkedin_page, pinterest, google_business, instagram, instagram_direct, tiktok, youtube, threads, bluesky. (A network key is not on the list.)\n\nnetworks must hold at least one network. (networks is missing or empty.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "You are not authorised to manage this workspace. (The app does not count you as a member of the workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/account_details": {
            "post": {
                "tags": [
                    "Account & Settings"
                ],
                "summary": "Who the API key belongs to: name, email, timezone, plan, default workspace and queue state.",
                "description": "Returns the account record of the key owner (never of a workspace owner), so it does not take `workspace_id`. `queue` tells whether the owner's whole posting queue is paused, the switch `/api/queue_pause` flips.",
                "operationId": "account_details",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": []
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "account": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted user id, the same value `/api/user_login` returns."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "First and last name."
                                                },
                                                "email": {
                                                    "type": "string",
                                                    "format": "email",
                                                    "description": "Account email."
                                                },
                                                "timezone": {
                                                    "type": "string",
                                                    "description": "Account timezone, e.g. `Asia/Kolkata`. Queue times and the dates of the owner's workspaces are shown in it."
                                                },
                                                "plan": {
                                                    "type": "string",
                                                    "description": "Plan name, e.g. `Pro`. Empty when no plan is attached."
                                                },
                                                "default_workspace_id": {
                                                    "type": "string",
                                                    "description": "Encrypted id of the signup workspace, the one used when a call omits `workspace_id`."
                                                },
                                                "member_since": {
                                                    "type": "string",
                                                    "format": "date",
                                                    "description": "Signup date."
                                                },
                                                "queue": {
                                                    "type": "object",
                                                    "properties": {
                                                        "status": {
                                                            "type": "string",
                                                            "description": "`running` or `paused`."
                                                        },
                                                        "resume_at": {
                                                            "type": "string",
                                                            "format": "date-time",
                                                            "description": "When a paused queue resumes by itself, in the account timezone. Empty when running or paused with no end."
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "account": {
                                        "id": "nX2k9Qp7Lw==",
                                        "name": "Jane Doe",
                                        "email": "you@example.com",
                                        "timezone": "Asia/Kolkata",
                                        "plan": "Pro",
                                        "default_workspace_id": "wS1dF2gH==",
                                        "member_since": "2024-05-18",
                                        "queue": {
                                            "status": "paused",
                                            "resume_at": "2026-12-01 16:00:00"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/account_timezone": {
            "post": {
                "tags": [
                    "Account & Settings"
                ],
                "summary": "Set the time zone of the account that owns the API key.",
                "description": "Changes the key owner's own time zone: the zone the app shows the calendar and queue in, and the zone every date of this API is shown in when the key owner is also the workspace owner. The value is matched against the IANA list in any case (`europe/london` is accepted) and the canonical spelling is saved and returned. A name that is not an IANA zone is refused here, where the app's own check would have fallen back to New York.\nThere is no `workspace_id`: a team member changes their own zone, never the owner's.",
                "operationId": "account_timezone",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "timezone": {
                                        "type": "string",
                                        "description": "IANA zone name, in any case, for example `America/New_York` or `asia/kolkata`.",
                                        "example": "Europe/London"
                                    }
                                },
                                "required": [
                                    "timezone"
                                ],
                                "example": {
                                    "timezone": "Europe/London"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Time zone updated.`"
                                        },
                                        "timezone": {
                                            "type": "string",
                                            "description": "The zone as saved, in its canonical spelling."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Time zone updated.",
                                    "timezone": "Europe/London"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "timezone must be an IANA zone name such as America/New_York. (timezone is missing or is not a name on the IANA list.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/account_update": {
            "post": {
                "tags": [
                    "Account & Settings"
                ],
                "summary": "Update the name, email, persona, expected account count or profile photo of the key owner's profile.",
                "description": "Updates the key owner's own profile. Send any of `first_name`, `last_name`, `email`, `persona`, `min_social_accounts` and `photo_url`; fields left out keep their value (the current row is read first, because the app's own call blanks whatever it is not sent). There is no `workspace_id`.\nA new `email` is not swapped in. The app mails a verification link to the new address and keeps the old one until it is confirmed, so `account.email` still shows the old address, `account.pending_email` the new one and `account.email_verification_sent` is `true`.",
                "operationId": "account_update",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "first_name": {
                                        "type": "string",
                                        "description": "First name; trimmed, must not be blank when sent.",
                                        "example": "Ann"
                                    },
                                    "last_name": {
                                        "type": "string",
                                        "description": "Last name; trimmed, must not be blank when sent.",
                                        "example": "Lee"
                                    },
                                    "email": {
                                        "type": "string",
                                        "format": "email",
                                        "description": "New login email. Starts the verification flow described above; the old address stays in use until the link is clicked.",
                                        "example": "ann@example.com"
                                    },
                                    "persona": {
                                        "type": "integer",
                                        "description": "What the account is for, as a code: 1 Blogger, 2 Coach, 3 Digital marketing professional, 4 Solopreneur, 5 Micro-entrepreneur, 6 Large-scale corporation, 7 Marketing agency, 8 Solo marketer, 9 Entrepreneur, 10 Other.",
                                        "enum": [
                                            1,
                                            2,
                                            3,
                                            4,
                                            5,
                                            6,
                                            7,
                                            8,
                                            9,
                                            10
                                        ],
                                        "example": 7
                                    },
                                    "min_social_accounts": {
                                        "type": "integer",
                                        "description": "How many social accounts the owner expects to manage, as a code: 1 Up to 10, 2 Up to 20, 3 Up to 50, 4 Up to 100, 5 Up to 500, 6 More than 500.",
                                        "enum": [
                                            1,
                                            2,
                                            3,
                                            4,
                                            5,
                                            6
                                        ],
                                        "example": 2
                                    },
                                    "photo_url": {
                                        "type": "string",
                                        "description": "New profile photo: the URL of an image you uploaded with `/api/media_upload_url` under your own account. Any other URL is refused. The previous photo is removed from storage.",
                                        "example": "https://cdn.recurpost.com/media/12345/images/me.png"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Profile updated.`, or `Profile updated; a verification link was sent to the new email address.` when the email changed."
                                        },
                                        "account": {
                                            "type": "object",
                                            "properties": {
                                                "first_name": {
                                                    "type": "string",
                                                    "description": "First name as saved."
                                                },
                                                "last_name": {
                                                    "type": "string",
                                                    "description": "Last name as saved."
                                                },
                                                "email": {
                                                    "type": "string",
                                                    "format": "email",
                                                    "description": "The login email in use; unchanged until a new address is verified."
                                                },
                                                "pending_email": {
                                                    "type": "string",
                                                    "description": "The new address waiting for verification, or an empty string."
                                                },
                                                "email_verification_sent": {
                                                    "type": "boolean",
                                                    "description": "`true` when this call sent a verification link."
                                                },
                                                "persona": {
                                                    "type": "integer",
                                                    "description": "Persona code, 1 to 10."
                                                },
                                                "persona_label": {
                                                    "type": "string",
                                                    "description": "The persona's label."
                                                },
                                                "min_social_accounts": {
                                                    "type": "integer",
                                                    "description": "Expected account count code, 1 to 6."
                                                },
                                                "min_social_accounts_label": {
                                                    "type": "string",
                                                    "description": "The code's label."
                                                },
                                                "photo_url": {
                                                    "type": "string",
                                                    "description": "The profile photo URL after the update; empty when the owner has none."
                                                },
                                                "timezone": {
                                                    "type": "string",
                                                    "description": "The owner's time zone; change it with `/api/account_timezone`."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Profile updated; a verification link was sent to the new email address.",
                                    "account": {
                                        "first_name": "Ann",
                                        "last_name": "Lee",
                                        "email": "old@example.com",
                                        "pending_email": "ann@example.com",
                                        "email_verification_sent": true,
                                        "persona": 7,
                                        "persona_label": "Marketing agency",
                                        "min_social_accounts": 2,
                                        "min_social_accounts_label": "Up to 20",
                                        "photo_url": "https://cdn.recurpost.com/media/12345/images/me.png",
                                        "timezone": "Asia/Kolkata"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Nothing to update: send first_name, last_name, email, persona, min_social_accounts or photo_url. (None of the six fields was sent.)\n\nphoto_url must be a file uploaded through media_upload_url. (photo_url is not on RecurPost storage under the caller's own folder.)\n\nfirst_name cannot be blank. (first_name (or last_name, named in the message) was sent empty or as whitespace.)\n\nemail must be a valid email address. (email does not parse as an address.)\n\npersona must be a code from 1 to 10: 1 Blogger, 2 Coach, 3 Digital marketing professional, 4 Solopreneur, 5 Micro-entrepreneur, 6 Large-scale corporation, 7 Marketing agency, 8 Solo marketer, 9 Entrepreneur, 10 Other. (persona is outside 1 to 10.)\n\nmin_social_accounts must be a code from 1 to 6: 1 Up to 10, 2 Up to 20, 3 Up to 50, 4 Up to 100, 5 Up to 500, 6 More than 500. (min_social_accounts is outside 1 to 6.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "That email address belongs to another account. (The new email is already registered to another RecurPost user.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; a message from the app replaces the default, with the app's own status, when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/account_limits": {
            "post": {
                "tags": [
                    "Account & Settings"
                ],
                "summary": "Plan limits of the workspace owner and how much of each is used.",
                "description": "Returns the plan of the workspace owner with each limit paired with its current usage, add-ons included, so an integration can check before it creates something. Limits follow the owner of the workspace, not the caller: a team member calling with a shared `workspace_id` sees the owner's plan.\n`posts_per_day` is counted per social account per day. The response lists every account of the workspace (or only `account_ids`) with the posts it already has on `date`, today in the owner's timezone by default, and how many more it may take. Each account's day runs in that account's own timezone, exactly as the limit check on `/api/post_content` counts it.",
                "operationId": "account_limits",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Day to count posts on, `YYYY-MM-DD`. Defaults to today in the owner's timezone.",
                                        "default": "today",
                                        "example": "2026-10-23"
                                    },
                                    "account_ids": {
                                        "type": "string",
                                        "description": "Encrypted social account ids from `/api/social_account_list`; one id, a comma-separated list or an array. Only these accounts are listed under `posts_per_day`. Defaults to every account of the workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "plan": {
                                            "type": "string",
                                            "description": "Plan name of the workspace owner."
                                        },
                                        "limits": {
                                            "type": "object",
                                            "properties": {
                                                "social_accounts": {
                                                    "type": "object",
                                                    "properties": {
                                                        "used": {
                                                            "type": "integer",
                                                            "description": "Connected social accounts across all of the owner's workspaces."
                                                        },
                                                        "limit": {
                                                            "type": "integer",
                                                            "description": "Social accounts the plan allows, add-ons included."
                                                        }
                                                    }
                                                },
                                                "library_content": {
                                                    "type": "object",
                                                    "properties": {
                                                        "used": {
                                                            "type": "integer",
                                                            "description": "Posts stored in libraries."
                                                        },
                                                        "limit": {
                                                            "type": "integer",
                                                            "description": "Library posts the plan allows."
                                                        }
                                                    }
                                                },
                                                "feeds": {
                                                    "type": "object",
                                                    "properties": {
                                                        "used": {
                                                            "type": "integer",
                                                            "description": "RSS feeds set up."
                                                        },
                                                        "limit": {
                                                            "type": "integer",
                                                            "description": "RSS feeds the plan allows."
                                                        }
                                                    }
                                                },
                                                "schedules": {
                                                    "type": "object",
                                                    "properties": {
                                                        "used": {
                                                            "type": "integer",
                                                            "description": "Library schedule slots in use."
                                                        },
                                                        "limit": {
                                                            "type": "integer",
                                                            "description": "Schedule slots the plan allows."
                                                        }
                                                    }
                                                },
                                                "team_members": {
                                                    "type": "object",
                                                    "properties": {
                                                        "used": {
                                                            "type": "integer",
                                                            "description": "Team members, the owner's own seat not counted."
                                                        },
                                                        "limit": {
                                                            "type": "integer",
                                                            "description": "Team members the plan allows."
                                                        }
                                                    }
                                                },
                                                "posts_per_day": {
                                                    "type": "object",
                                                    "properties": {
                                                        "limit": {
                                                            "type": "integer",
                                                            "description": "Posts one social account may publish per day (one-off and library posts added together)."
                                                        },
                                                        "date": {
                                                            "type": "string",
                                                            "format": "date",
                                                            "description": "The day the counts below are for."
                                                        },
                                                        "accounts": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "array",
                                                                "items": [],
                                                                "description": "One row per account of the workspace, or per account in `account_ids`, by name.",
                                                                "properties": {
                                                                    "account_id": {
                                                                        "type": "string",
                                                                        "description": "Encrypted social account id."
                                                                    },
                                                                    "name": {
                                                                        "type": "string",
                                                                        "description": "Account name."
                                                                    },
                                                                    "network": {
                                                                        "type": "string",
                                                                        "description": "facebook, instagram, twitter, linkedin, pinterest, google_my_business, tiktok, youtube, threads or bluesky."
                                                                    },
                                                                    "status": {
                                                                        "type": "string",
                                                                        "description": "`active`, `paused` or `needs_reconnection`."
                                                                    },
                                                                    "used": {
                                                                        "type": "integer",
                                                                        "description": "Posts already on this account on `date`, in the account's timezone; deleted posts are not counted."
                                                                    },
                                                                    "remaining": {
                                                                        "type": "integer",
                                                                        "description": "`limit` minus `used`, never below 0."
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "plan": "Pro",
                                    "limits": {
                                        "social_accounts": {
                                            "used": 2,
                                            "limit": 7
                                        },
                                        "library_content": {
                                            "used": 1,
                                            "limit": 100
                                        },
                                        "feeds": {
                                            "used": 1,
                                            "limit": 3
                                        },
                                        "schedules": {
                                            "used": 1,
                                            "limit": 20
                                        },
                                        "team_members": {
                                            "used": 1,
                                            "limit": 4
                                        },
                                        "posts_per_day": {
                                            "limit": 35,
                                            "date": "2026-10-23",
                                            "accounts": [
                                                {
                                                    "account_id": "nX2k9Qp7Lw==",
                                                    "name": "My Page",
                                                    "network": "facebook",
                                                    "status": "active",
                                                    "used": 2,
                                                    "remaining": 33
                                                },
                                                {
                                                    "account_id": "Qm7Zt3Vb1A==",
                                                    "name": "My Studio",
                                                    "network": "instagram",
                                                    "status": "active",
                                                    "used": 0,
                                                    "remaining": 35
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "At most 50 ids per call; N were sent. (More than 50 account ids.)\n\naccount_ids holds an invalid id. (An account id does not decrypt.)\n\ndate must be YYYY-MM-DD. (date is not a valid calendar day in that form.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (An account in account_ids is not the workspace owner's or is not in the workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nNo plan found for this account. (The workspace owner has no plan row.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/plan_details": {
            "post": {
                "tags": [
                    "Account & Settings"
                ],
                "summary": "The workspace owner's plan: name, billing cycle, where it was bought, its state, features and limits.",
                "description": "Returns the plan of the workspace owner as a reader needs it. Prices, order ids and the payment provider's links stay inside the app. The plan follows the owner of the workspace, not the caller: a team member calling with a shared `workspace_id` sees the owner's plan. For the limits paired with their current usage call `/api/account_limits`.\n`status` is `free` on a free plan, `trial` during a free trial, `cancelled` when a paid plan has an end date that has not passed yet (access runs until `ends_at`), otherwise `active`.",
                "operationId": "plan_details",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "plan": {
                                            "type": "object",
                                            "properties": {
                                                "name": {
                                                    "type": "string",
                                                    "description": "Plan name."
                                                },
                                                "billing_cycle": {
                                                    "type": "string",
                                                    "description": "`free`, `monthly`, `yearly` or `other`."
                                                },
                                                "source": {
                                                    "type": "string",
                                                    "description": "Where the plan was bought: `free`, `web`, `android` or `ios`."
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "`free`, `trial`, `cancelled` or `active`."
                                                },
                                                "is_trial": {
                                                    "type": "boolean",
                                                    "description": "`true` during a free trial."
                                                },
                                                "ends_at": {
                                                    "type": "string",
                                                    "description": "When access ends on a cancelled plan, `YYYY-MM-DD HH:MM:SS`; an empty string when there is no end date."
                                                },
                                                "features": {
                                                    "type": "object",
                                                    "properties": {
                                                        "reports": {
                                                            "type": "boolean",
                                                            "description": "Reports are included."
                                                        },
                                                        "dm_automation": {
                                                            "type": "boolean",
                                                            "description": "DM automation is included."
                                                        }
                                                    }
                                                },
                                                "limits": {
                                                    "type": "object",
                                                    "properties": {
                                                        "social_accounts": {
                                                            "type": "integer",
                                                            "description": "Social accounts the plan allows."
                                                        },
                                                        "posts_per_day": {
                                                            "type": "integer",
                                                            "description": "Posts one social account may publish per day."
                                                        },
                                                        "one_off_posts": {
                                                            "type": "integer",
                                                            "description": "One-off posts allowed."
                                                        },
                                                        "schedules": {
                                                            "type": "integer",
                                                            "description": "Library schedule slots allowed."
                                                        },
                                                        "feeds": {
                                                            "type": "integer",
                                                            "description": "RSS feeds allowed."
                                                        },
                                                        "team_members": {
                                                            "type": "integer",
                                                            "description": "Team members allowed."
                                                        },
                                                        "recurring_posts": {
                                                            "type": "integer",
                                                            "description": "Recurring (library) posts allowed."
                                                        },
                                                        "ai_posts": {
                                                            "type": "integer",
                                                            "description": "AI generated posts allowed."
                                                        },
                                                        "shareable_calendars": {
                                                            "type": "integer",
                                                            "description": "Shareable calendars allowed."
                                                        },
                                                        "storage_gb": {
                                                            "type": "number",
                                                            "description": "Media storage in GB."
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "plan": {
                                        "name": "Pro",
                                        "billing_cycle": "yearly",
                                        "source": "web",
                                        "status": "active",
                                        "is_trial": false,
                                        "ends_at": "",
                                        "features": {
                                            "reports": true,
                                            "dm_automation": false
                                        },
                                        "limits": {
                                            "social_accounts": 5,
                                            "posts_per_day": 40,
                                            "one_off_posts": 15,
                                            "schedules": 20,
                                            "feeds": 3,
                                            "team_members": 4,
                                            "recurring_posts": 300,
                                            "ai_posts": 25,
                                            "shareable_calendars": 2,
                                            "storage_gb": 50
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nNo plan found for this workspace owner. (The workspace owner has no plan row.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/billing_invoices": {
            "post": {
                "tags": [
                    "Account & Settings"
                ],
                "summary": "The key owner's payments, newest first, with the invoice link of each.",
                "description": "Lists every payment of the workspace owner: date, what was bought, the amount and a link to the invoice at the payment provider. Only the workspace owner's own key may read them; a team member gets 403. The list is not paged. The stored provider response never leaves the app.",
                "operationId": "billing_invoices",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. The caller must be the owner of that workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "total": {
                                            "type": "integer",
                                            "description": "Number of invoices."
                                        },
                                        "invoices": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "date": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When the order was placed."
                                                    },
                                                    "item": {
                                                        "type": "string",
                                                        "description": "What was bought, comma-separated when the order had several items; an empty string when the stored order carries no item names."
                                                    },
                                                    "amount": {
                                                        "type": "string",
                                                        "description": "Amount charged, as a decimal string in the order's currency."
                                                    },
                                                    "invoice_url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Link to the invoice at the payment provider; may be an empty string for an order whose stored event carries none."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "total": 2,
                                    "invoices": [
                                        {
                                            "date": "2026-10-01 10:00:00",
                                            "item": "extra-accounts, extra-storage",
                                            "amount": "5.00",
                                            "invoice_url": "https://sites.fastspring.com/recurpost/order/invoice/RP-2"
                                        },
                                        {
                                            "date": "2026-09-01 10:00:00",
                                            "item": "Professional Yearly",
                                            "amount": "29.00",
                                            "invoice_url": "https://sites.fastspring.com/recurpost/order/invoice/RP-1"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can read the invoices. (The key belongs to a team member, not the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/storage_usage": {
            "post": {
                "tags": [
                    "Account & Settings"
                ],
                "summary": "Media storage used against the workspace owner's allowance.",
                "description": "Returns how much media storage the workspace owner uses and how much the plan allows, add-on units included. Any member of the workspace may read it; the figures are the owner's. The app refreshes the used figure from storage at most once a minute, so `last_checked_at` says how fresh it is.",
                "operationId": "storage_usage",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "storage": {
                                            "type": "object",
                                            "properties": {
                                                "used_bytes": {
                                                    "type": "integer",
                                                    "description": "Bytes stored."
                                                },
                                                "limit_bytes": {
                                                    "type": "integer",
                                                    "description": "Bytes the plan allows, add-ons included."
                                                },
                                                "limit_gb": {
                                                    "type": "number",
                                                    "description": "The same limit in GB."
                                                },
                                                "percent_used": {
                                                    "type": "number",
                                                    "description": "`used_bytes` as a share of `limit_bytes`, one decimal; 0 when the limit is 0."
                                                },
                                                "extra_storage_units": {
                                                    "type": "integer",
                                                    "description": "Storage add-on units bought."
                                                },
                                                "last_checked_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "description": "When the used figure was last read from storage."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "storage": {
                                        "used_bytes": 536870912,
                                        "limit_bytes": 2147483648,
                                        "limit_gb": 2,
                                        "percent_used": 25,
                                        "extra_storage_units": 1,
                                        "last_checked_at": "2026-10-22 08:00:00"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/queue_pause": {
            "post": {
                "tags": [
                    "Account & Settings"
                ],
                "summary": "Pause or resume the whole posting queue of the workspace owner.",
                "description": "Pauses every scheduled post of the account until you resume it, or until `resume_at` when you send one. Only the workspace owner's own key may use it; a team member gets 403. The switch is account wide, not per workspace: pausing from any of the owner's workspaces pauses all of them.\n\nCheck the state: `/api/account_details` returns the current queue state and the resume time.",
                "operationId": "queue_pause",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "What to do. Case does not matter.",
                                        "enum": [
                                            "pause",
                                            "resume"
                                        ],
                                        "example": "pause"
                                    },
                                    "resume_at": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "With `action=pause` only: when the queue resumes by itself, `YYYY-MM-DD HH:MM:SS` in the account owner's timezone. Must be in the future. Ignored on resume.",
                                        "example": "2026-12-01 10:00:00"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. Its owner must be you.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "action"
                                ],
                                "example": {
                                    "action": "pause"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Queue paused.` or `Queue resumed.`"
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Queue paused."
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "action must be pause or resume. (action is missing or another word.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nresume_at must be YYYY-MM-DD HH:MM:SS in your timezone. (resume_at is sent with a pause and is not a valid datetime in that exact format.)\n\nPlease select a future date and time to pause the queue. (resume_at is in the past.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can pause the queue. (The workspace belongs to someone else (the verb follows the action: pause or resume).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The queue could not be updated. (The app answered without a usable status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/x_wallet": {
            "post": {
                "tags": [
                    "Account & Settings"
                ],
                "summary": "Balance of the X (Twitter) URL wallet, posts it still covers, top-up packs and transactions; read or set the Permit Repeated Tweets rule.",
                "description": "Posts to X carry a per-post cost that is paid from the workspace owner's wallet. This call returns the balance, how many posts it still covers, the cost per post, the threshold below which RecurPost warns, and the top-up packs on offer. When the key belongs to the wallet owner the latest transactions are included too, 20 a page; a team member reading a shared workspace gets the wallet without `transactions`.\n`permit_repeated_tweets` is the owner's X posting rule from the X settings page of the app: whether evergreen library posts and their variations may go out on X again after they have posted once. It is read here, and the workspace owner sets it here by sending `permit_repeated_tweets` with the call; the wallet comes back with the new state. It is not a notification and /api/email_preferences does not list or accept it.\n\nTop-ups happen in the app: There is no endpoint to buy a pack; the `sku` values match the packs on the X wallet page in RecurPost.",
                "operationId": "x_wallet",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. The wallet read is the workspace owner's.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Transactions page, 20 per page. Only used when the wallet is your own.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "permit_repeated_tweets": {
                                        "type": "boolean",
                                        "description": "Library posts and their variations may go out on X again after they have posted once. Send it to set the rule before the wallet is read: `true`, `1`, `yes` or `on` allows the repeats; any other value stops them. Workspace owner only. Omit to read.",
                                        "example": true
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "wallet": {
                                            "type": "object",
                                            "properties": {
                                                "balance_usd": {
                                                    "type": "number",
                                                    "description": "Current balance in USD."
                                                },
                                                "posts_remaining": {
                                                    "type": "integer",
                                                    "description": "Posts to X the balance still covers."
                                                },
                                                "cost_per_post_usd": {
                                                    "type": "number",
                                                    "description": "What one post to X costs."
                                                },
                                                "low_balance_threshold_usd": {
                                                    "type": "number",
                                                    "description": "Balance under which RecurPost sends a low-balance warning."
                                                },
                                                "topup_packs": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "sku": {
                                                                "type": "string",
                                                                "description": "Pack identifier."
                                                            },
                                                            "price_usd": {
                                                                "type": "number",
                                                                "description": "What the pack costs."
                                                            },
                                                            "credit_usd": {
                                                                "type": "number",
                                                                "description": "Credit the pack adds to the wallet."
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        },
                                        "permit_repeated_tweets": {
                                            "type": "boolean",
                                            "description": "Whether the owner lets library posts repeat on X. The state after this call's save, when it carried `permit_repeated_tweets`."
                                        },
                                        "transactions": {
                                            "type": "object",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "type": {
                                                                "type": "string",
                                                                "description": "Transaction type, e.g. `topup` or a debit for a post. Present only for the wallet owner's own key."
                                                            },
                                                            "amount_usd": {
                                                                "type": "number",
                                                                "description": "Amount of the transaction."
                                                            },
                                                            "balance_after_usd": {
                                                                "type": "number",
                                                                "description": "Balance once it was applied."
                                                            },
                                                            "note": {
                                                                "type": "string",
                                                                "description": "Free text attached to the transaction."
                                                            },
                                                            "date": {
                                                                "type": "string",
                                                                "description": "When it happened, in the owner's timezone."
                                                            }
                                                        }
                                                    }
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Transactions in all."
                                                },
                                                "page": {
                                                    "type": "integer",
                                                    "description": "Page returned."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Rows per page, 20."
                                                },
                                                "total_pages": {
                                                    "type": "integer",
                                                    "description": "Number of pages."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "wallet": {
                                        "balance_usd": 12.5,
                                        "posts_remaining": 25,
                                        "cost_per_post_usd": 0.5,
                                        "low_balance_threshold_usd": 2,
                                        "topup_packs": [
                                            {
                                                "sku": "pack10",
                                                "price_usd": 10,
                                                "credit_usd": 12
                                            }
                                        ]
                                    },
                                    "permit_repeated_tweets": false,
                                    "transactions": {
                                        "items": [
                                            {
                                                "type": "topup",
                                                "amount_usd": 10,
                                                "balance_after_usd": 12.5,
                                                "note": "Pack",
                                                "date": "2026-10-01 10:00"
                                            }
                                        ],
                                        "total": 1,
                                        "page": 1,
                                        "per_page": 20,
                                        "total_pages": 1
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "You are not a member of this workspace. (The app does not count you as an active team member of the wallet owner.)\n\nOnly the workspace owner can change the X posting rule. (permit_repeated_tweets was sent by a team member of a shared workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not save permit_repeated_tweets; a message from the app replaces the default when it sent one.)\n\nThe wallet could not be read. (The app answered without a usable status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/custom_fields": {
            "post": {
                "tags": [
                    "Account & Settings"
                ],
                "summary": "List, create, rename and delete custom fields, and set each account's value for them.",
                "description": "Custom fields are per-account values substituted into post text: a field named `City` is written as `[[City]]` in a post and each account publishes its own value. One endpoint handles them through `action`: `list` (the default), `create` (with `name` and optional `values`), `rename` (`field_id`, `name`), `set_value` (`field_id`, `account_id`, `value`; adds or replaces), `delete_value` (`field_id`, `account_id`) and `delete` (`field_id`, `confirm=true`). Every action answers with the full list as it stands afterwards.\nAny member may list; every other action needs the workspace owner's own key. `field_id` is a plain integer from the list; `account_id` is an encrypted string from `/api/social_account_list`.\n\nDeleting a field does not edit posts: Posts that still carry `[[name]]` publish the placeholder as written once the field is gone.",
                "operationId": "custom_fields",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "What to do.",
                                        "enum": [
                                            "list",
                                            "create",
                                            "rename",
                                            "set_value",
                                            "delete_value",
                                            "delete"
                                        ],
                                        "default": "list",
                                        "example": "list"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "field_id": {
                                        "type": "integer",
                                        "description": "Plain integer id of the field from the list. Required for rename, set_value, delete_value and delete.",
                                        "example": 3
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "Field name, 1 to 50 characters; the placeholder becomes `[[name]]`. Required for create and rename.",
                                        "example": "City"
                                    },
                                    "values": {
                                        "type": "array",
                                        "items": [],
                                        "description": "For create: the first values, as an array (or JSON string) of objects with `account_id` (encrypted) and `value` (1 to 500 characters).",
                                        "example": [
                                            {
                                                "account_id": "aB3dE5fG==",
                                                "value": "Pune"
                                            }
                                        ]
                                    },
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted social account id. Required for set_value and delete_value.",
                                        "example": "aB3dE5fG=="
                                    },
                                    "value": {
                                        "type": "string",
                                        "description": "The account's value, 1 to 500 characters. Required for set_value.",
                                        "example": "Mumbai"
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be `true` for delete.",
                                        "example": true
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`, `Custom field created.`, `Custom field renamed.`, `Value saved.`, `Value removed.` or `Custom field deleted.` by action."
                                        },
                                        "custom_fields": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain integer field id."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Field name."
                                                    },
                                                    "placeholder": {
                                                        "type": "string",
                                                        "description": "The text to write in a post, `[[name]]`."
                                                    },
                                                    "values": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "object",
                                                            "properties": {
                                                                "account": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "id": {
                                                                            "type": "string",
                                                                            "description": "Encrypted social account id."
                                                                        },
                                                                        "name": {
                                                                            "type": "string",
                                                                            "description": "Account name."
                                                                        },
                                                                        "network": {
                                                                            "type": "string",
                                                                            "description": "facebook, instagram, twitter, linkedin, pinterest, google_my_business, tiktok, youtube, threads or bluesky."
                                                                        }
                                                                    }
                                                                },
                                                                "value": {
                                                                    "type": "string",
                                                                    "description": "The value this account publishes in place of the placeholder."
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Value saved.",
                                    "custom_fields": [
                                        {
                                            "id": 3,
                                            "name": "City",
                                            "placeholder": "[[City]]",
                                            "values": [
                                                {
                                                    "account": {
                                                        "id": "aB3dE5fG==",
                                                        "name": "My Page",
                                                        "network": "facebook"
                                                    },
                                                    "value": "Mumbai"
                                                }
                                            ]
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\naction must be list, create, rename, set_value, delete_value or delete. (action is another value.)\n\nname must be 1 to 50 characters. (create or rename with a blank name or one over 50 characters.)\n\nvalues items need account_id and a value of 1 to 500 characters. (A values item has no decryptable account_id or a value that is blank or over 500 characters.)\n\naccount_id is required. (set_value or delete_value without a decryptable account_id.)\n\nvalue must be 1 to 500 characters. (set_value with a blank value or one over 500 characters.)\n\nSend confirm=true to delete the field and every account's value for it; posts still carrying its placeholder keep the text as written. (delete without confirm=true.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can change custom fields. (Any action but list from a team member's key.)\n\nSorry, there was an issue. Please try again later or contact support. (An account_id (in values or on its own) is not an account of the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nfield_id is not one of this account's custom fields; see action list. (rename, set_value, delete_value or delete with a field_id the owner does not have.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and an account is not in that workspace.)\n\nThis account has no value for the field. (delete_value for an account that has no value.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "A custom field with that name exists already. (create or rename with a name already in use.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/email_preferences": {
            "post": {
                "tags": [
                    "Account & Settings"
                ],
                "summary": "List the key owner's email and push notification preferences, or switch one.",
                "description": "Without `email_type` lists the key owner's notification preferences with their current state; with `email_type` and `enabled` saves one. The list is the caller's own and there is no `workspace_id`; the set of types depends on the account (account owners also see the `workflow_` toggles), so read the list before saving and send only a type it offers.\nTypes a user sees: `daily_editorial`, `daily_editorial_no_schedule`, `post_failure_email`, `post_failure_notification`, `weekly_summary_report`, `team_member_push_notification`, `inbox_summary_report`, `pause_queue_email`, `social_profile_disconnection_email`, `post_success_email`, `post_success_notification`, `daily_posting_summary` and, for owners, the workflow toggles. `daily_posting_summary` also takes the time of day the summary is sent.\nThe Permit Repeated Tweets rule is not a notification and is not listed here; it lives under X settings in the app and is read and set on /api/x_wallet.",
                "operationId": "email_preferences",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "email_type": {
                                        "type": "string",
                                        "description": "The preference to save, one of the `email_type` values the list returns. Omit to list.",
                                        "example": "post_success_email"
                                    },
                                    "enabled": {
                                        "type": "boolean",
                                        "description": "Required with `email_type`. `true`, `1`, `yes` or `on` turns it on; any other value turns it off.",
                                        "example": true
                                    },
                                    "send_hour": {
                                        "type": "integer",
                                        "description": "For `daily_posting_summary` only, required there: hour of the day 1 to 12.",
                                        "example": 9
                                    },
                                    "send_minute": {
                                        "type": "integer",
                                        "description": "For `daily_posting_summary` only, required there: minute 0 to 59.",
                                        "example": 30
                                    },
                                    "send_meridiem": {
                                        "type": "string",
                                        "description": "For `daily_posting_summary` only, required there: `AM` or `PM`, in any case.",
                                        "enum": [
                                            "AM",
                                            "PM"
                                        ],
                                        "example": "AM"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success` on a list, `Preference saved.` on a save."
                                        },
                                        "preferences": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "email_type": {
                                                        "type": "string",
                                                        "description": "Preference key (list only)."
                                                    },
                                                    "label": {
                                                        "type": "string",
                                                        "description": "Label as the settings page shows it, without markup."
                                                    },
                                                    "enabled": {
                                                        "type": "boolean",
                                                        "description": "Current state."
                                                    },
                                                    "send_hour": {
                                                        "type": "string",
                                                        "description": "On `daily_posting_summary` only: hour 1 to 12 as a string, empty when never set."
                                                    },
                                                    "send_minute": {
                                                        "type": "string",
                                                        "description": "On `daily_posting_summary` only: minute as a string."
                                                    },
                                                    "send_meridiem": {
                                                        "type": "string",
                                                        "description": "On `daily_posting_summary` only: `AM` or `PM`."
                                                    }
                                                }
                                            }
                                        },
                                        "preference": {
                                            "type": "object",
                                            "properties": {
                                                "email_type": {
                                                    "type": "string",
                                                    "description": "The preference saved (save only)."
                                                },
                                                "enabled": {
                                                    "type": "boolean",
                                                    "description": "The state saved."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "preferences": [
                                        {
                                            "email_type": "daily_editorial",
                                            "label": "Daily scheduled content email",
                                            "enabled": true
                                        },
                                        {
                                            "email_type": "post_success_email",
                                            "label": "Get email on successful posts",
                                            "enabled": false
                                        },
                                        {
                                            "email_type": "daily_posting_summary",
                                            "label": "Daily posting summary",
                                            "enabled": true,
                                            "send_hour": "9",
                                            "send_minute": "30",
                                            "send_meridiem": "AM"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "email_type is not one of your preferences; call without it to list them. (email_type is not in the caller's list.)\n\npermit_repeated_tweets is an X posting rule, not a notification; save it with /api/x_wallet. (email_type is permit_repeated_tweets.)\n\nenabled is required with email_type. (email_type was sent without enabled.)\n\ndaily_posting_summary needs send_hour (1-12), send_minute (0-59) and send_meridiem (AM or PM). (Saving daily_posting_summary with a missing or out-of-range time.)\n\nYou have insufficient permissions to perform this action. (The app does not find the caller's own team seat.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/working_hours": {
            "post": {
                "tags": [
                    "Account & Settings"
                ],
                "summary": "Read or set the workspace owner's working hours, which the workflow timers follow.",
                "description": "Without `days` lists the workspace owner's working hours; with `days` saves all seven and lists them back. Approval timeouts and reminders of the workflow only count working time, so this is where that clock is set. Only the workspace owner's own key may call it, as on the settings page. Times are wall-clock times in the owner's time zone, on the hour or half hour. An owner who never saved them gets the default: Monday to Friday 09:00 to 17:00, weekend off.\n\nChecked here, not in the app: The app's own save replaces a bad time with 09:00 and 17:00 without a word; this endpoint refuses the whole list instead, and nothing is saved when any day fails.",
                "operationId": "working_hours",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. The caller must be the owner of that workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "days": {
                                        "type": "array",
                                        "items": [],
                                        "description": "All seven days, as an array (or JSON string) of objects with `day` (1 Monday to 7 Sunday), `is_working` (boolean) and, for a working day, `start_time` and `end_time` as `HH:MM` on the hour or half hour with start before end. Omit to read.",
                                        "example": [
                                            {
                                                "day": 1,
                                                "is_working": true,
                                                "start_time": "09:00",
                                                "end_time": "17:30"
                                            },
                                            {
                                                "day": 2,
                                                "is_working": true,
                                                "start_time": "09:00",
                                                "end_time": "17:30"
                                            },
                                            {
                                                "day": 3,
                                                "is_working": true,
                                                "start_time": "09:00",
                                                "end_time": "17:30"
                                            },
                                            {
                                                "day": 4,
                                                "is_working": true,
                                                "start_time": "09:00",
                                                "end_time": "17:30"
                                            },
                                            {
                                                "day": 5,
                                                "is_working": true,
                                                "start_time": "09:00",
                                                "end_time": "16:00"
                                            },
                                            {
                                                "day": 6,
                                                "is_working": false
                                            },
                                            {
                                                "day": 7,
                                                "is_working": false
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success` on a read, `Working hours saved.` after a save."
                                        },
                                        "working_hours": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "day": {
                                                        "type": "integer",
                                                        "description": "1 Monday to 7 Sunday."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Day name."
                                                    },
                                                    "is_working": {
                                                        "type": "boolean",
                                                        "description": "Whether the day counts as working time."
                                                    },
                                                    "start_time": {
                                                        "type": "string",
                                                        "description": "`HH:MM` in the owner's time zone."
                                                    },
                                                    "end_time": {
                                                        "type": "string",
                                                        "description": "`HH:MM` in the owner's time zone."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Working hours saved.",
                                    "working_hours": [
                                        {
                                            "day": 1,
                                            "name": "Monday",
                                            "is_working": true,
                                            "start_time": "09:00",
                                            "end_time": "17:30"
                                        },
                                        {
                                            "day": 2,
                                            "name": "Tuesday",
                                            "is_working": true,
                                            "start_time": "09:00",
                                            "end_time": "17:30"
                                        },
                                        {
                                            "day": 3,
                                            "name": "Wednesday",
                                            "is_working": true,
                                            "start_time": "09:00",
                                            "end_time": "17:30"
                                        },
                                        {
                                            "day": 4,
                                            "name": "Thursday",
                                            "is_working": true,
                                            "start_time": "09:00",
                                            "end_time": "17:30"
                                        },
                                        {
                                            "day": 5,
                                            "name": "Friday",
                                            "is_working": true,
                                            "start_time": "09:00",
                                            "end_time": "16:00"
                                        },
                                        {
                                            "day": 6,
                                            "name": "Saturday",
                                            "is_working": false,
                                            "start_time": "09:00",
                                            "end_time": "17:00"
                                        },
                                        {
                                            "day": 7,
                                            "name": "Sunday",
                                            "is_working": false,
                                            "start_time": "09:00",
                                            "end_time": "17:00"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nEach entry needs a day from 1 (Monday) to 7 (Sunday). (A days entry has no day or one outside 1 to 7.)\n\nDay N needs is_working. (A days entry has no is_working.)\n\nDay N: start_time and end_time must be HH:MM on the hour or half hour. (A working day has a time that is missing, not HH:MM, or not on :00 or :30.)\n\nDay N: start_time must be earlier than end_time. (A working day ends before or when it starts.)\n\nAll seven days are required. (days does not cover every day from 1 to 7.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Working hours are set by the workspace owner. (The key belongs to a team member, not the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/notifications": {
            "post": {
                "tags": [
                    "Account & Settings"
                ],
                "summary": "RecurPost's product announcements, newest first, with how many the key owner has not seen.",
                "description": "Lists the in-app announcements RecurPost publishes (new features, changes), newest first, with the number the key owner has not seen yet. Reading does not mark them seen; send `mark_read=true` to record the newest one as seen, which resets `unread_count` on the next call. The list is the same for every user; only the unread count is the caller's. No `workspace_id`. Ids are plain integers.",
                "operationId": "notifications",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "page": {
                                        "type": "integer",
                                        "description": "Page number, from 1.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "per_page": {
                                        "type": "integer",
                                        "description": "Items per page, 1 to 50.",
                                        "default": "20",
                                        "example": 20
                                    },
                                    "mark_read": {
                                        "type": "boolean",
                                        "description": "`true` marks every announcement up to the newest as seen. The `unread_count` in this same answer is the count before the mark.",
                                        "default": "false",
                                        "example": false
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "unread_count": {
                                            "type": "integer",
                                            "description": "Announcements newer than the last one the caller saw, before this call's `mark_read`."
                                        },
                                        "page": {
                                            "type": "integer",
                                            "description": "The page returned."
                                        },
                                        "per_page": {
                                            "type": "integer",
                                            "description": "The page size used."
                                        },
                                        "notifications": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain integer announcement id."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Announcement title."
                                                    },
                                                    "link": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Where the announcement points."
                                                    },
                                                    "created_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When it was published."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "unread_count": 2,
                                    "page": 1,
                                    "per_page": 20,
                                    "notifications": [
                                        {
                                            "id": 318,
                                            "title": "Bluesky video posts are here",
                                            "link": "https://recurpost.com/blog/bluesky-video",
                                            "created_at": "2026-10-20 09:00:00"
                                        },
                                        {
                                            "id": 317,
                                            "title": "New: approval workflows for agencies",
                                            "link": "https://recurpost.com/blog/approval-workflows",
                                            "created_at": "2026-10-12 09:00:00"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/branding": {
            "post": {
                "tags": [
                    "Account & Settings"
                ],
                "summary": "Read, set or remove the workspace owner's white-label logo for reports.",
                "description": "The logo printed on the owner's report PDFs in place of RecurPost's. `action` is `get` (the default, open to every member), `set` with a `logo_url` you uploaded through `/api/media_upload_url`, or `delete`. `set` and `delete` need the workspace owner's own key.",
                "operationId": "branding",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "What to do.",
                                        "enum": [
                                            "get",
                                            "set",
                                            "delete"
                                        ],
                                        "default": "get",
                                        "example": "get"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "logo_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "For `set`, required there: the URL of an image you uploaded with `/api/media_upload_url` under your own account. Any other URL is refused.",
                                        "example": "https://cdn.recurpost.com/media/4821/images/logo.png"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`, `Report logo saved.` or `Report logo removed.` by action."
                                        },
                                        "logo_url": {
                                            "type": "string",
                                            "description": "The logo in place after the call; an empty string when there is none."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Report logo saved.",
                                    "logo_url": "https://cdn.recurpost.com/media/4821/images/logo.png"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\naction must be get, set or delete. (action is another value.)\n\nlogo_url must be a file uploaded through media_upload_url. (set with a URL that is not on RecurPost storage under the owner's folder.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can change the report logo. (set or delete from a team member's key.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/account_group_list": {
            "post": {
                "tags": [
                    "Account Groups"
                ],
                "summary": "List every account group of the workspace owner with the ids of its accounts.",
                "description": "Returns all groups of the workspace owner, sorted by name, empty groups included. Each group carries the encrypted ids of its accounts; call `/api/account_group` for the account names and states.",
                "operationId": "account_group_list",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. Groups are read for that workspace's owner.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "groups": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted group id."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Group name."
                                                    },
                                                    "color": {
                                                        "type": "string",
                                                        "description": "Hex color shown in the app, e.g. `#6366f1`."
                                                    },
                                                    "account_count": {
                                                        "type": "integer",
                                                        "description": "Number of accounts in the group."
                                                    },
                                                    "account_ids": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "string",
                                                            "description": "Encrypted ids of the accounts in the group, the same ids `/api/social_account_list` returns."
                                                        }
                                                    },
                                                    "created_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When the group was created, UTC."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "groups": [
                                        {
                                            "id": "gR1pQ2sT==",
                                            "name": "Brands",
                                            "color": "#112233",
                                            "account_count": 2,
                                            "account_ids": [
                                                "aB3dE5fG==",
                                                "hJ7kL9mN=="
                                            ],
                                            "created_at": "2026-10-01 10:00:00"
                                        },
                                        {
                                            "id": "kL3mN4oP==",
                                            "name": "Empty",
                                            "color": "#6366f1",
                                            "account_count": 0,
                                            "account_ids": [],
                                            "created_at": "2026-10-05 08:30:00"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/account_group": {
            "post": {
                "tags": [
                    "Account Groups"
                ],
                "summary": "Read one group with its accounts.",
                "description": "Returns one group of the workspace owner with its accounts listed by name, each with its network key and state. The accounts are sorted by name.",
                "operationId": "account_group",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted group id from `/api/account_group_list`. Exactly one id.",
                                        "example": "gR1pQ2sT=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": "gR1pQ2sT=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "group": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted group id."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Group name."
                                                },
                                                "color": {
                                                    "type": "string",
                                                    "description": "Hex color."
                                                },
                                                "account_count": {
                                                    "type": "integer",
                                                    "description": "Number of accounts in the group."
                                                },
                                                "created_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "description": "When the group was created, UTC."
                                                },
                                                "accounts": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "description": "Encrypted account id."
                                                            },
                                                            "network": {
                                                                "type": "string",
                                                                "description": "Network key: `facebook`, `twitter`, `linkedin`, `instagram`, `pinterest`, `google_my_business`, `tiktok`, `youtube`, `threads` or `bluesky`."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Account name on the network."
                                                            },
                                                            "status": {
                                                                "type": "string",
                                                                "description": "`active`, `paused` or `needs_reconnection`."
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "group": {
                                        "id": "gR1pQ2sT==",
                                        "name": "Brands",
                                        "color": "#112233",
                                        "account_count": 2,
                                        "created_at": "2026-10-01 10:00:00",
                                        "accounts": [
                                            {
                                                "id": "aB3dE5fG==",
                                                "network": "facebook",
                                                "name": "Alpha page",
                                                "status": "active"
                                            },
                                            {
                                                "id": "hJ7kL9mN==",
                                                "network": "twitter",
                                                "name": "Bird",
                                                "status": "paused"
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nA valid id is required. (id is missing, does not decrypt, or holds more than one id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nGroup not found. (No group with that id belongs to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/account_group_create": {
            "post": {
                "tags": [
                    "Account Groups"
                ],
                "summary": "Create a group with a name, an optional color and optional accounts.",
                "description": "Creates a group for the workspace owner. Every account id must belong to the owner (and, when you name a workspace, sit in that workspace); the ids are checked before anything is written, so a bad id leaves nothing behind. Group names are unique per owner.",
                "operationId": "account_group_create",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "description": "Group name. Leading and trailing spaces are trimmed; must be unique among the owner's groups.",
                                        "example": "Brands"
                                    },
                                    "color": {
                                        "type": "string",
                                        "description": "Six-digit hex color with the leading `#`. Stored lower case.",
                                        "default": "#6366f1",
                                        "example": "#6366f1"
                                    },
                                    "account_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted account ids from `/api/social_account_list`: an array, or one string with ids separated by commas. Duplicates are dropped. Leave out for an empty group.",
                                        "example": [
                                            "aB3dE5fG==",
                                            "hJ7kL9mN=="
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. When sent, every account must be part of that workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "name"
                                ],
                                "example": {
                                    "name": "Brands"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Group created.`"
                                        },
                                        "id": {
                                            "type": "string",
                                            "description": "Encrypted id of the new group."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Group created.",
                                    "id": "gR1pQ2sT=="
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nname is required. (name is missing or blank.)\n\ncolor must be a hex value like #6366f1. (color is sent and is not #RRGGBB.)\n\naccount_ids holds an invalid id. (One of the ids does not decrypt.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (One of the accounts does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and one of the accounts is not in that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "A group with this name already exists (The owner already has a group with that name.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The group could not be created. (The app answered without a usable status; any other app error text is relayed with status 400.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/account_group_update": {
            "post": {
                "tags": [
                    "Account Groups"
                ],
                "summary": "Rename, recolor or replace the accounts of a group.",
                "description": "Changes one group of the workspace owner. A field you leave out keeps its value. `account_ids`, when sent, replaces the whole set of accounts, so send the complete list you want to end up with, not the delta.\nThe list may not end up empty: the app deletes a group whose last account is removed, so this endpoint refuses an empty list with 400 and asks you to call `/api/account_group_delete` instead if that is what you want.\n\nAn empty group cannot be updated: A group created without accounts has nothing to keep, so a rename or recolor of it fails with the \"at least one account\" error unless the same call also sends `account_ids`.",
                "operationId": "account_group_update",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted group id from `/api/account_group_list`.",
                                        "example": "gR1pQ2sT=="
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "New name. Blank keeps the current name.",
                                        "example": "Renamed"
                                    },
                                    "color": {
                                        "type": "string",
                                        "description": "New six-digit hex color with the leading `#`. Blank keeps the current color.",
                                        "example": "#000000"
                                    },
                                    "account_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "The full new set of encrypted account ids: an array, or one string with ids separated by commas. Replaces the current accounts. Must hold at least one id.",
                                        "example": [
                                            "hJ7kL9mN=="
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. When sent, every account in `account_ids` must be part of that workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": "gR1pQ2sT=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Group updated.`"
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Group updated."
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nA valid id is required. (id is missing, does not decrypt, or holds more than one id.)\n\ncolor must be a hex value like #6366f1. (color is sent and is not #RRGGBB.)\n\naccount_ids holds an invalid id. (account_ids is sent and one of the ids does not decrypt.)\n\nA group needs at least one account. Use account_group_delete to remove it. (account_ids is sent empty, or the group is empty and no account_ids are sent.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (One of the accounts does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nGroup not found. (No group with that id belongs to the workspace owner.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and one of the accounts is not in that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "A group with this name already exists (Another group of the owner has the new name.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The group could not be updated. (The app answered without a usable status; any other app error text is relayed with status 400.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/account_group_delete": {
            "post": {
                "tags": [
                    "Account Groups"
                ],
                "summary": "Delete a group.",
                "description": "Deletes one group of the workspace owner. The accounts in it are untouched; only the grouping goes. Posts that were created through the group keep their accounts.",
                "operationId": "account_group_delete",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted group id from `/api/account_group_list`.",
                                        "example": "gR1pQ2sT=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": "gR1pQ2sT=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Group deleted.`"
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Group deleted."
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nA valid id is required. (id is missing, does not decrypt, or holds more than one id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nGroup not found. (No group with that id belongs to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The group could not be deleted. (The app answered without a usable status; any other app error text is relayed with status 400.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/post_status": {
            "post": {
                "tags": [
                    "Posts"
                ],
                "summary": "Where a post stands on every account it was sent to.",
                "description": "Returns one entry per social account a post went to, with its queue item id, its state, the time it is or was published in that account's timezone, the permalink once published and the failure reason when it failed. `id` is the plain integer that `/api/post_content` returns as `post_data.id` and `/api/history_data` returns as `id`, so you store one value and poll it.\n\nTimezone per account: `post_date` is shown in each account's timezone, not the workspace owner's, so two accounts of one post can show different clock times for the same instant.",
                "operationId": "post_status",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Plain integer post id (`post_data.id` from `/api/post_content`). Not encrypted.",
                                        "example": 901
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. When given, only the post's accounts that sit in this workspace are listed.",
                                        "example": "wS9kLm2Qp1=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 901
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "id": {
                                            "type": "integer",
                                            "description": "The post id you asked for."
                                        },
                                        "accounts": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "One entry per social account, oldest post time first.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted social account id, as in `/api/social_account_list`."
                                                    },
                                                    "queue_item_id": {
                                                        "type": "integer",
                                                        "description": "Queue item id of this account's row (plain integer). Pass it to `/api/post_retry` when the row is `failed`, or to the queue endpoints while it is scheduled."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Account name."
                                                    },
                                                    "network": {
                                                        "type": "string",
                                                        "description": "`facebook`, `twitter`, `linkedin`, `instagram`, `pinterest`, `google_my_business`, `tiktok`, `youtube`, `threads` or `bluesky`."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "`scheduled`, `published`, `failed`, `deleted` or `pending` (in flight)."
                                                    },
                                                    "post_date": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "Scheduled or actual publish time, `YYYY-MM-DD HH:MM:SS` in the social account's own timezone (UTC when it has none)."
                                                    },
                                                    "post_link": {
                                                        "type": "string",
                                                        "description": "Permalink on the network once published; empty before that, for Facebook stories, and when the post was later removed from the network."
                                                    },
                                                    "fail_reason": {
                                                        "type": "string",
                                                        "description": "Only present when `status` is `failed` and a reason was recorded."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "id": 901,
                                    "accounts": [
                                        {
                                            "id": "aC3dEf4Gh5==",
                                            "queue_item_id": 4120,
                                            "name": "Acme Store",
                                            "network": "facebook",
                                            "status": "published",
                                            "post_date": "2026-10-01 10:00:00",
                                            "post_link": "https://www.facebook.com/104455_987654321"
                                        },
                                        {
                                            "id": "bD4eFg5Hi6==",
                                            "queue_item_id": 4121,
                                            "name": "@acmestore",
                                            "network": "twitter",
                                            "status": "failed",
                                            "post_date": "2026-10-01 05:00:00",
                                            "post_link": "",
                                            "fail_reason": "Rate limited"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id missing or not a positive integer.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The post does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not one of your workspaces or your membership is not active.)\n\nPost not found. (No account rows exist for the id (or none inside the named workspace).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/instagram_locations": {
            "post": {
                "tags": [
                    "Posts"
                ],
                "summary": "Search Instagram places to tag a post with.",
                "description": "Searches Instagram places matching `search_text` through one of the workspace's connected Instagram business accounts (or the account named by `id`). Pass the returned `id` and `name` as `in_location_id` and `in_location_name` on `/api/post_content` or the library calls to tag the post with the place.\n\nLive network call: Every call queries Instagram's Graph API through the account's token; results are not cached and count against Meta's own rate limits for that account.",
                "operationId": "instagram_locations",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "search_text": {
                                        "type": "string",
                                        "description": "Place name or address fragment to search for.",
                                        "example": "Pune"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS9kLm2Qp1=="
                                    },
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted social account id of the Instagram business account to search through. Defaults to one of the workspace's connected Instagram business accounts.",
                                        "example": "aC3dEf4Gh5=="
                                    }
                                },
                                "required": [
                                    "search_text"
                                ],
                                "example": {
                                    "search_text": "Pune"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "locations": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Matching places, as Instagram returned them; may be empty.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Instagram place id, the value for `in_location_id`."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Place name, the value for `in_location_name`."
                                                    },
                                                    "city": {
                                                        "type": "string",
                                                        "description": "City, empty when Instagram sent none."
                                                    },
                                                    "country": {
                                                        "type": "string",
                                                        "description": "Country, empty when Instagram sent none."
                                                    },
                                                    "latitude": {
                                                        "type": "number",
                                                        "description": "Latitude, or null."
                                                    },
                                                    "longitude": {
                                                        "type": "number",
                                                        "description": "Longitude, or null."
                                                    },
                                                    "link": {
                                                        "type": "string",
                                                        "description": "Facebook page link of the place, or empty."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "locations": [
                                        {
                                            "id": "212988663",
                                            "name": "Pune, Maharashtra",
                                            "city": "Pune",
                                            "country": "India",
                                            "latitude": 18.5204,
                                            "longitude": 73.8567,
                                            "link": "https://www.facebook.com/212988663"
                                        },
                                        {
                                            "id": "108296975869040",
                                            "name": "Pune Railway Station",
                                            "city": "",
                                            "country": "",
                                            "latitude": null,
                                            "longitude": null,
                                            "link": ""
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "search_text is required. (search_text missing or blank.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nA valid id is required. (id was sent but does not decrypt to one account id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (id is not an account of the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not one of your workspaces or your membership is not active.)\n\nThis social account is not part of the selected workspace. (id is the owner's account but not in the named workspace_id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Please connect an Instagram business account ... / Please re-connect ... (The workspace has no usable Instagram business account, or its token needs reconnecting. The exact text comes from the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Instagram did not answer the location search. (Instagram's API returned an error or nothing; any error text Instagram sent replaces this message.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/url_preview": {
            "post": {
                "tags": [
                    "Posts"
                ],
                "summary": "The link preview RecurPost would show for a URL: title, description, image and the other images on the page.",
                "description": "Reads a public web page the way the composer does when a link is pasted and returns its title, description, the preview image and the other images found on the page, so an integration can pick an image or show the card before it calls `/api/post_content`. YouTube and Vimeo links get their video details. The page is fetched by RecurPost's servers during the call, through the same public-URL guard as media: private, loopback and reserved addresses are refused. No `workspace_id`.\nA page that cannot be read still answers 200: `preview.found` is `false`, the text fields are empty and `message` says so.\n\nFetched during the call: The page is downloaded while the request runs, so a slow site makes the call slow. Nothing is stored; pass the chosen image to `/api/post_content` as `image_url` yourself.",
                "operationId": "url_preview",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public http or https address of the page.",
                                        "example": "https://example.com/blog/plan-a-month-of-posts"
                                    }
                                },
                                "required": [
                                    "url"
                                ],
                                "example": {
                                    "url": "https://example.com/blog/plan-a-month-of-posts"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`, or `The page could not be read.` when `preview.found` is false."
                                        },
                                        "preview": {
                                            "type": "object",
                                            "properties": {
                                                "url": {
                                                    "type": "string",
                                                    "format": "uri",
                                                    "description": "The page URL as resolved; the one you sent when the page gave none."
                                                },
                                                "host": {
                                                    "type": "string",
                                                    "description": "Host name of the page."
                                                },
                                                "title": {
                                                    "type": "string",
                                                    "description": "Page title; empty when the page could not be read."
                                                },
                                                "description": {
                                                    "type": "string",
                                                    "description": "Page description; empty when the page could not be read."
                                                },
                                                "image_url": {
                                                    "type": "string",
                                                    "format": "uri",
                                                    "description": "The preview image the composer would pick; empty when none."
                                                },
                                                "images": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Other images found on the page, blanks removed."
                                                    }
                                                },
                                                "found": {
                                                    "type": "boolean",
                                                    "description": "`false` when the page answered with a not-found placeholder."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "preview": {
                                        "url": "https://example.com/blog/plan-a-month-of-posts",
                                        "host": "example.com",
                                        "title": "Plan a month of posts in one sitting",
                                        "description": "Three ways to fill a content calendar without burning out.",
                                        "image_url": "https://example.com/img/og-plan.jpg",
                                        "images": [
                                            "https://example.com/img/og-plan.jpg",
                                            "https://example.com/img/calendar.png"
                                        ],
                                        "found": true
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "url must be a public http or https address. (url is missing, is not a URL, has another scheme, or its host resolves to a private, loopback or reserved address.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/shorten_url": {
            "post": {
                "tags": [
                    "Posts"
                ],
                "summary": "Shorten a link with one of the key owner's attached URL shortener accounts.",
                "description": "Shortens a public URL with a shortener account attached to the key owner's RecurPost account (Bitly or a self-hosted Shlink, as set up under Settings or with `/api/shortener_accounts`). `shortener_id` picks the account; the first attached account is used when it is left out. A URL that is already short comes back as it is. No `workspace_id`: shortener accounts belong to the key owner.\n`shortener_id` is a plain integer.",
                "operationId": "shorten_url",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public http or https address to shorten.",
                                        "example": "https://example.com/blog/plan-a-month-of-posts?utm_source=api"
                                    },
                                    "shortener_id": {
                                        "type": "integer",
                                        "description": "Plain integer id of one of your shortener accounts (see `/api/shortener_accounts`). Defaults to the first one.",
                                        "example": 12
                                    }
                                },
                                "required": [
                                    "url"
                                ],
                                "example": {
                                    "url": "https://example.com/blog/plan-a-month-of-posts?utm_source=api"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "url": {
                                            "type": "string",
                                            "format": "uri",
                                            "description": "The URL you sent."
                                        },
                                        "short_url": {
                                            "type": "string",
                                            "format": "uri",
                                            "description": "The short link; the original URL when the shortener returned none."
                                        },
                                        "shortener_id": {
                                            "type": "integer",
                                            "description": "The shortener account used."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "url": "https://example.com/blog/plan-a-month-of-posts?utm_source=api",
                                    "short_url": "https://bit.ly/4abcDeF",
                                    "shortener_id": 12
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "url must be a public http or https address. (url is missing, is not a URL, has another scheme, or its host resolves to a private, loopback or reserved address.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "shortener_id is not one of your shortener accounts. (shortener_id belongs to someone else or does not exist.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "No URL shortener account is attached to your account; attach one under Settings or with shortener_accounts. (The key owner has no shortener account.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The shortener or the app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/post_content": {
            "post": {
                "tags": [
                    "Posts"
                ],
                "summary": "Publish a post now, or schedule it, on one or more social accounts.",
                "description": "Creates a one-off post on the social accounts in `id` and publishes it immediately or at `schedule_date_time`. One call makes one post with one entry per account; the response carries the post id you poll with `/api/post_status`.\nThe post is built once and saved as one tab per network (Facebook, Twitter/X, LinkedIn, Instagram, Google Business, Pinterest, YouTube, TikTok, Threads, Bluesky) from the same fields, so you can send every network option in one call and each account picks up its own. `message`, `image_url`, `video_url` and `url` are the shared content; `fb_`, `tw_`, `ln_`, `in_`, `gmb_` / `gbp_`, `pi_`, `yt_`, `tk_`, `th_` and `bs_` prefixed fields override text or add options for one network, and `<prefix>_image_url` / `<prefix>_video_url` give one network media of its own.\nThe post type follows the media: text only, link (a `url` or a link in the text, with a fetched preview), image (up to 20), video (mp4 or mov), or mixed when both images and a video are given. Every media URL is downloaded by RecurPost's servers, so it must be publicly reachable; upload the file through `/api/media_upload_url` first to skip that download.\nThe call runs the checks in this order: ids and ownership, media URL reachability, the option checks (400), the schedule time (400 / 415), the owner's daily post limit (403), then the media is fetched and stored (403 / 415) and the post saved; the app's content validator answers 422 with per-network details.\n\nPost now vs scheduled: Without `schedule_date_time` the post is queued for immediate publishing (schedule mode `post now`). With it, the time is stored as wall-clock time in the workspace owner's timezone, which is what `/api/post_status` and the app's calendar show.\n\nMedia is fetched synchronously: Images, videos, thumbnails and LinkedIn documents are downloaded and stored during the call; a large video makes the request take as long as the download. Hosts behind authentication, private addresses or expiring links fail with 415. Google Drive share links are resolved to their download URL.\n\nPer-network overrides: A `<prefix>_message` equal to `message` is not treated as a customisation. On a text post a different per-network message gets its own link preview from the first link in that text. `alt_text`, covers (`fb_thumb`, `ln_thumb`, `in_thumb`), post types and first comments only mark the tab as customised when they apply (a cover on a post without video is dropped silently).\n\nPinterest destination: When any chosen account is Pinterest, `url` (or the first link in the text) is saved as the pin's destination link, normalised with `http://` when the scheme is missing. An invalid value answers 415 `Invalid url parameter supplied`.\n\nInstagram extras: Location, image tags, reel tags, collaborators, music, the trial flag and product tags are saved only on the Instagram tab. `in_image_tags` and `in_product_tags` positions refer to `in_image_url` positions when Instagram has its own images, else to `image_url` positions and are stored against the hosted copy of that image. Usernames are stored without the leading `@` and de-duplicated. Music (`in_audio_*`), `in_trial_reel` and `in_reel_product_tags` are kept on reels only and dropped silently on a feed or story post once the option checks have passed; music needs an account connected through Facebook login, see `/api/instagram_audio_search`.\n\nFacebook page mentions: `fb_mentions` lists the pages; the text has to carry `@<page id>` where each mention goes, as `/api/mention_search` returns the id. The publisher rewrites each into Facebook's mention form when it posts to a Page.\n\nGoogle Business CTA: `gbp_cta=None` clears the button and both links. An `Offer` CTA with `gbp_cta_url` and no `gbp_redeem_offer_link` uses the CTA link as the redeem link. A link post with no CTA gets `Learn more` pointing at the link automatically.\n\nTwitter/X thread: `twitter_thread` items become follow-up tweets under the main tweet. Each item's media is hosted the same way as the main post's; a thread item with a video needs the same paid plan as `video_url`. The thread is ignored by every other network.\n\nPlan rules follow the workspace owner: Video uploads, the daily post limit and media quotas are checked against the workspace owner's plan, not the caller's, when a team member posts into someone else's workspace.\n\nPer-network media: A network can post media of its own: `<prefix>_image_url` and `<prefix>_video_url` (`fb_`, `tw_`, `ln_`, `in_`, `gmb_`, `pi_`, `yt_`, `tk_`, `th_`, `bs_`) replace `image_url` / `video_url` on that network only and mark its tab as customised. Each network keeps its own cap (Facebook 15, Twitter/X 4, LinkedIn 20, Instagram 10 in all, Google Business 1, Pinterest 1, TikTok 10, Threads 20 in all, Bluesky 4); only Instagram and Threads combine images with a video, ordered by `in_media_order` / `th_media_order`; YouTube takes `yt_video_url` only. A URL named by several networks is downloaded once. Covers (`fb_thumb` and the others) apply to whichever video that network ends up with; `in_image_tags` and `in_product_tags` positions count in `in_image_url` when Instagram has its own images. Removing all media from one network is not possible: an empty override answers 400.\n\nLegacy endpoint: with body or Basic credentials errors arrive as HTTP 200 with the real status in the body field `status`. With a Bearer token it returns real HTTP status codes.",
                "operationId": "post_content",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted social account id from `/api/social_account_list`. Several accounts take a JSON array or a comma-separated string; the same post then goes to all of them. Every id must decrypt or the whole call answers 400.",
                                        "example": [
                                            "aC3dEf4Gh5==",
                                            "bD4eFg5Hi6=="
                                        ]
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "Post text. `\\r\\n` is normalised to `\\n`. Links in it are detected for the preview and, on Pinterest, for the pin's destination.",
                                        "example": "Check out our amazing summer sale! https://example.com/summer-sale"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS9kLm2Qp1=="
                                    },
                                    "schedule_date_time": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When to publish. Leave out to publish now. `YYYY-MM-DD HH:MM:SS` is read as wall-clock time in the workspace owner's timezone; an ISO 8601 value with an offset or `Z` (`2026-10-20T09:30:00+05:30`) is honoured as given. Must be in the future. The misspelt legacy name `shedule_date_time` is still accepted.",
                                        "example": "2026-12-25 10:00:00"
                                    },
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link to share with the post. On a text post the page's title, description and image are fetched and saved as the link preview; when omitted, the first link found in `message` is used instead. On a Pinterest account the value becomes the pin's destination link. `http://` is prepended when the scheme is missing. The host must be a public address.",
                                        "example": "https://example.com/summer-sale"
                                    },
                                    "image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Image URLs, in display order. Send a JSON array (or repeat `image_url[]` in form encoding); a single string is accepted as a one-item list. At most 20 images. Each URL must be a publicly reachable http or https URL and answer an image content type. URLs returned by `/api/media_upload_url` are used as they are; every other URL is copied to RecurPost storage unless `host_images_on_recurpost` is off. May be combined with `video_url` into a mixed post.",
                                        "example": [
                                            "https://example.com/sale1.jpg",
                                            "https://example.com/sale2.jpg"
                                        ]
                                    },
                                    "video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A public mp4 or mov URL (Google Drive share links are accepted and resolved to the download URL). The file is downloaded and stored on RecurPost storage, so the call takes as long as the download; a URL from `/api/media_upload_url` skips the download. Needs a paid plan. Files are limited to 2 GB.",
                                        "example": "https://example.com/promo.mp4"
                                    },
                                    "media_order": {
                                        "type": "array",
                                        "items": [],
                                        "description": "The order of a mixed post's media as a list of the original URLs given in `image_url` and `video_url`. Media left out of the list follow, video first. Only read when both images and a video are sent. Any URL not in `image_url` / `video_url` answers 400.",
                                        "example": [
                                            "https://example.com/promo.mp4",
                                            "https://example.com/sale1.jpg"
                                        ]
                                    },
                                    "host_images_on_recurpost": {
                                        "type": "boolean",
                                        "description": "Copy images and custom thumbnails to RecurPost storage (the default). Send `false`, `0` or the form string `\"false\"` to keep your own URLs instead; they must then stay reachable until every post using them has been published.",
                                        "default": "true",
                                        "example": true
                                    },
                                    "alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text per image, in `image_url` order; a single string applies to the first image. At most 1000 characters each. Saved on the Facebook, Twitter/X, LinkedIn, Pinterest, Threads and Bluesky tabs; Instagram does not take alt text here.",
                                        "example": [
                                            "Two models in summer outfits",
                                            "Store front with sale banner"
                                        ]
                                    },
                                    "fb_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Facebook accounts instead of `image_url`, same rules and hosting as `image_url`. At most 15 images on Facebook. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `fb_video_url`.",
                                        "example": [
                                            "https://example.com/fb-square.jpg"
                                        ]
                                    },
                                    "fb_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Facebook accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `fb_image_url`.",
                                        "example": "https://example.com/fb-clip.mp4"
                                    },
                                    "fb_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `fb_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "tw_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Twitter/X accounts instead of `image_url`, same rules and hosting as `image_url`. At most 4 images on Twitter/X. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `tw_video_url`.",
                                        "example": [
                                            "https://example.com/tw-square.jpg"
                                        ]
                                    },
                                    "tw_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Twitter/X accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `tw_image_url`.",
                                        "example": "https://example.com/tw-clip.mp4"
                                    },
                                    "tw_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `tw_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "ln_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for LinkedIn accounts instead of `image_url`, same rules and hosting as `image_url`. At most 20 images on LinkedIn. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `ln_video_url`.",
                                        "example": [
                                            "https://example.com/ln-square.jpg"
                                        ]
                                    },
                                    "ln_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for LinkedIn accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `ln_image_url`.",
                                        "example": "https://example.com/ln-clip.mp4"
                                    },
                                    "ln_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `ln_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "in_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Instagram accounts instead of `image_url`, same rules and hosting as `image_url`. At most 10 media in all, images and video together on Instagram. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. May be combined with `in_video_url` into a carousel; `in_media_order` sets the order.",
                                        "example": [
                                            "https://example.com/in-square.jpg"
                                        ]
                                    },
                                    "in_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Instagram accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. May be combined with `in_image_url` into a carousel.",
                                        "example": "https://example.com/in-clip.mp4"
                                    },
                                    "in_media_order": {
                                        "type": "array",
                                        "items": [],
                                        "description": "The order of Instagram's own media as a list of the URLs given in `in_image_url` and `in_video_url`. Media left out of the list follow, video first. Only read when both are sent. Any other URL answers 400.",
                                        "example": [
                                            "https://example.com/in-clip.mp4",
                                            "https://example.com/in-square.jpg"
                                        ]
                                    },
                                    "gmb_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Google Business accounts instead of `image_url`, same rules and hosting as `image_url`. At most 1 image on Google Business. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `gmb_video_url`.",
                                        "example": [
                                            "https://example.com/gmb-square.jpg"
                                        ]
                                    },
                                    "gmb_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Google Business accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `gmb_image_url`.",
                                        "example": "https://example.com/gmb-clip.mp4"
                                    },
                                    "pi_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Pinterest accounts instead of `image_url`, same rules and hosting as `image_url`. At most 1 image on Pinterest. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `pi_video_url`.",
                                        "example": [
                                            "https://example.com/pi-square.jpg"
                                        ]
                                    },
                                    "pi_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Pinterest accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `pi_image_url`.",
                                        "example": "https://example.com/pi-clip.mp4"
                                    },
                                    "pi_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `pi_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "yt_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for YouTube accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. YouTube takes a video only, so there is no `yt_image_url`.",
                                        "example": "https://example.com/yt-clip.mp4"
                                    },
                                    "tk_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for TikTok accounts instead of `image_url`, same rules and hosting as `image_url`. At most 10 images on TikTok. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `tk_video_url`.",
                                        "example": [
                                            "https://example.com/tk-square.jpg"
                                        ]
                                    },
                                    "tk_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for TikTok accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `tk_image_url`.",
                                        "example": "https://example.com/tk-clip.mp4"
                                    },
                                    "th_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Threads accounts instead of `image_url`, same rules and hosting as `image_url`. At most 20 media in all, images and video together on Threads. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. May be combined with `th_video_url` into a carousel; `th_media_order` sets the order.",
                                        "example": [
                                            "https://example.com/th-square.jpg"
                                        ]
                                    },
                                    "th_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Threads accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. May be combined with `th_image_url` into a carousel.",
                                        "example": "https://example.com/th-clip.mp4"
                                    },
                                    "th_media_order": {
                                        "type": "array",
                                        "items": [],
                                        "description": "The order of Threads's own media as a list of the URLs given in `th_image_url` and `th_video_url`. Media left out of the list follow, video first. Only read when both are sent. Any other URL answers 400.",
                                        "example": [
                                            "https://example.com/th-clip.mp4",
                                            "https://example.com/th-square.jpg"
                                        ]
                                    },
                                    "th_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `th_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "bs_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Bluesky accounts instead of `image_url`, same rules and hosting as `image_url`. At most 4 images on Bluesky. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `bs_video_url`.",
                                        "example": [
                                            "https://example.com/bs-square.jpg"
                                        ]
                                    },
                                    "bs_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Bluesky accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `bs_image_url`.",
                                        "example": "https://example.com/bs-clip.mp4"
                                    },
                                    "bs_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `bs_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "fb_message": {
                                        "type": "string",
                                        "description": "Text for Facebook accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #facebook"
                                    },
                                    "tw_message": {
                                        "type": "string",
                                        "description": "Text for Twitter/X accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #twitter"
                                    },
                                    "ln_message": {
                                        "type": "string",
                                        "description": "Text for LinkedIn accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #linkedin"
                                    },
                                    "in_message": {
                                        "type": "string",
                                        "description": "Text for Instagram accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #instagram"
                                    },
                                    "gmb_message": {
                                        "type": "string",
                                        "description": "Text for Google Business accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #googlebusiness"
                                    },
                                    "pi_message": {
                                        "type": "string",
                                        "description": "Text for Pinterest accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #pinterest"
                                    },
                                    "yt_message": {
                                        "type": "string",
                                        "description": "Text for YouTube accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview. On YouTube this is the video description.",
                                        "example": "Summer sale is here! #youtube"
                                    },
                                    "tk_message": {
                                        "type": "string",
                                        "description": "Text for TikTok accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #tiktok"
                                    },
                                    "th_message": {
                                        "type": "string",
                                        "description": "Text for Threads accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #threads"
                                    },
                                    "bs_message": {
                                        "type": "string",
                                        "description": "Text for Bluesky accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #bluesky"
                                    },
                                    "first_comment": {
                                        "type": "string",
                                        "description": "First comment posted right after the post, commonly hashtags. Applied on Facebook Pages, LinkedIn and Instagram feed posts unless a network-specific first comment is given.",
                                        "example": "#summer #sale #deals"
                                    },
                                    "fb_first_comment": {
                                        "type": "string",
                                        "description": "Facebook first comment; overrides `first_comment` on Facebook.",
                                        "example": "#facebook #summersale"
                                    },
                                    "ln_first_comment": {
                                        "type": "string",
                                        "description": "LinkedIn first comment; overrides `first_comment` on LinkedIn.",
                                        "example": "#linkedin #summersale"
                                    },
                                    "in_first_comment": {
                                        "type": "string",
                                        "description": "Instagram first comment (feed posts only); overrides `first_comment` on Instagram.",
                                        "example": "#instagram #summersale"
                                    },
                                    "fb_post_type": {
                                        "type": "string",
                                        "description": "Facebook post type. Case-insensitive; an unknown value keeps `feed`.",
                                        "enum": [
                                            "feed",
                                            "reel",
                                            "story"
                                        ],
                                        "default": "feed",
                                        "example": "feed"
                                    },
                                    "fb_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Custom cover image URL for the video on Facebook. Public image URL; copied to RecurPost storage unless `host_images_on_recurpost` is off. Ignored when the post has no `video_url`.",
                                        "example": "https://example.com/fb-cover.jpg"
                                    },
                                    "fb_mentions": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Facebook pages to mention, up to 10: page ids from `/api/mention_search`, as a JSON array of ids or of objects with `page_id` and `name`. Write `@<page id>` in the text where each mention should appear; the publisher turns it into the page's mention on Facebook Pages. An id that is not all digits answers 400.",
                                        "example": [
                                            {
                                                "page_id": "104857362001",
                                                "name": "Acme"
                                            }
                                        ]
                                    },
                                    "fb_background_id": {
                                        "type": "string",
                                        "description": "Facebook text background for a post without `image_url` or `video_url`: an id from `/api/facebook_backgrounds` (letters, digits, underscore or dash, up to 64 characters). Applied on Facebook pages only.",
                                        "example": "106"
                                    },
                                    "ln_document": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public URL of a document to post as a LinkedIn document (carousel) post: PDF, PPT, PPTX, DOC or DOCX, detected from the file bytes, not the file name. The file is downloaded and stored on RecurPost storage and the LinkedIn tab becomes a document post. A file of another type is left as given and ignored by the publisher. Google Drive share links are resolved.",
                                        "example": "https://example.com/catalog.pdf"
                                    },
                                    "ln_document_title": {
                                        "type": "string",
                                        "description": "Title shown on the LinkedIn document. Defaults to the file name without its extension.",
                                        "example": "Summer Catalog 2026"
                                    },
                                    "ln_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Custom cover image URL for the video on LinkedIn. Ignored when the post has no `video_url`.",
                                        "example": "https://example.com/ln-cover.jpg"
                                    },
                                    "in_post_type": {
                                        "type": "string",
                                        "description": "Instagram post type. Case-insensitive; an unknown value keeps `feed`. A reel needs a `video_url`.",
                                        "enum": [
                                            "feed",
                                            "story",
                                            "reel"
                                        ],
                                        "default": "feed",
                                        "example": "feed"
                                    },
                                    "in_reel_share_in_feed": {
                                        "type": "string",
                                        "description": "Whether a reel also appears in the profile feed. Only read when `in_post_type` is `reel`.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "in_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Custom cover image URL for an Instagram reel. Only applied when `in_post_type` is `reel` and the post has a `video_url`; copied to RecurPost storage because Meta fetches it at publish time.",
                                        "example": "https://example.com/in-cover.jpg"
                                    },
                                    "in_location_id": {
                                        "type": "string",
                                        "description": "Instagram place id to tag the post with. Take `id` and `name` from `/api/instagram_locations`. `in_location_name` is required with it.",
                                        "example": "212988663"
                                    },
                                    "in_location_name": {
                                        "type": "string",
                                        "description": "Name of the place in `in_location_id`, required with it.",
                                        "example": "Pune, Maharashtra"
                                    },
                                    "in_location_city": {
                                        "type": "string",
                                        "description": "City of the tagged place, as returned by `/api/instagram_locations`.",
                                        "example": "Pune"
                                    },
                                    "in_location_country": {
                                        "type": "string",
                                        "description": "Country of the tagged place, as returned by `/api/instagram_locations`.",
                                        "example": "India"
                                    },
                                    "in_image_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "People to tag on feed images. A JSON array of objects with `username`, `x` and `y` (fractions of the image width and height between 0 and 1) and `image` (1-based position in `image_url`, default 1). The leading `@` is optional. Any entry missing a username, with coordinates outside 0..1 or pointing past the last image answers 400.",
                                        "example": [
                                            {
                                                "image": 1,
                                                "username": "recurpost",
                                                "x": 0.5,
                                                "y": 0.4
                                            }
                                        ]
                                    },
                                    "in_reel_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Usernames to tag on a reel, as a JSON array or a comma-separated string. Only saved when the post has a `video_url`; answers 400 without one.",
                                        "example": [
                                            "recurpost",
                                            "jane_doe"
                                        ]
                                    },
                                    "in_collaborators": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Instagram usernames invited as collaborators, as a JSON array or a comma-separated string. At most 3; more answer 400.",
                                        "example": [
                                            "jane_doe"
                                        ]
                                    },
                                    "in_audio_id": {
                                        "type": "string",
                                        "description": "Music for an Instagram reel: a track id from `/api/instagram_audio_search`. Needs `in_post_type` `reel`, a `video_url` and `in_audio_account_id`; ignored on feed and story posts.",
                                        "example": "1012345678901234"
                                    },
                                    "in_audio_account_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the Instagram account the audio search ran for (the `account_id` in that answer). Required with `in_audio_id`.",
                                        "example": "Qm7Zt3Vb1A=="
                                    },
                                    "in_audio_type": {
                                        "type": "string",
                                        "description": "Kind of track, as the search returned it.",
                                        "enum": [
                                            "music",
                                            "original_sound"
                                        ],
                                        "default": "music",
                                        "example": "music"
                                    },
                                    "in_audio_title": {
                                        "type": "string",
                                        "description": "Track title from the search, stored for display.",
                                        "example": "Summer Days"
                                    },
                                    "in_audio_artist": {
                                        "type": "string",
                                        "description": "Artist from the search, stored for display.",
                                        "example": "The Planners"
                                    },
                                    "in_audio_duration_ms": {
                                        "type": "integer",
                                        "description": "Track length in milliseconds from the search; 0 when omitted.",
                                        "example": 30000
                                    },
                                    "in_audio_volume": {
                                        "type": "integer",
                                        "description": "Volume of the added track, 0 to 100.",
                                        "default": "100",
                                        "example": 60
                                    },
                                    "in_video_volume": {
                                        "type": "integer",
                                        "description": "Volume of the video's own sound under the track, 0 to 100; 0 mutes it.",
                                        "default": "100",
                                        "example": 100
                                    },
                                    "in_trial_reel": {
                                        "type": "string",
                                        "description": "Publish the reel as an Instagram trial reel (shown to non-followers first): `manual` leaves sharing to everyone up to you, `performance` lets Instagram share it when it does well. Reels only.",
                                        "enum": [
                                            "manual",
                                            "performance"
                                        ],
                                        "example": "performance"
                                    },
                                    "in_product_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Shopping tags on feed images. A JSON array of objects with `account_id` (encrypted Instagram account), `product_id` (from `/api/instagram_products`), `image` (1-based position in `image_url`, default 1), `x` and `y` (fractions 0 to 1, default 0.5) and optional `product_name` and `product_image` for display. Only kept on the Instagram tab.",
                                        "example": [
                                            {
                                                "account_id": "Qm7Zt3Vb1A==",
                                                "product_id": "6612345678901",
                                                "image": 1,
                                                "x": 0.3,
                                                "y": 0.7,
                                                "product_name": "Planner Mug",
                                                "product_image": "https://example.com/img/mug.jpg"
                                            }
                                        ]
                                    },
                                    "in_reel_product_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Shopping tags on a reel. A JSON array of objects with `account_id` (encrypted Instagram account), `product_id` (from `/api/instagram_products`) and optional `product_name` and `image_url` for display. Needs `in_post_type` `reel`.",
                                        "example": [
                                            {
                                                "account_id": "Qm7Zt3Vb1A==",
                                                "product_id": "6612345678901",
                                                "product_name": "Planner Mug",
                                                "image_url": "https://example.com/img/mug.jpg"
                                            }
                                        ]
                                    },
                                    "pi_title": {
                                        "type": "string",
                                        "description": "Pin title. The destination link of the pin is `url` or the first link in the text.",
                                        "example": "Summer Sale - Best Deals of the Season"
                                    },
                                    "gbp_cta": {
                                        "type": "string",
                                        "description": "Call-to-action button on the Google Business post. Case-insensitive. An unknown value or `None` saves no button. On a link post with no CTA given, `Learn more` pointing at the link is set automatically.",
                                        "enum": [
                                            "Learn more",
                                            "Sign up",
                                            "Buy",
                                            "Order online",
                                            "Book",
                                            "Call now",
                                            "Offer",
                                            "None"
                                        ],
                                        "default": "None",
                                        "example": "Learn more"
                                    },
                                    "gbp_cta_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link the button opens. Not used for `Call now`. With `gbp_cta=Offer` and no `gbp_redeem_offer_link`, this value doubles as the redeem link.",
                                        "example": "https://example.com/summer-sale"
                                    },
                                    "gbp_offer_title": {
                                        "type": "string",
                                        "description": "Offer title; offer fields are used when `gbp_cta` is `Offer`.",
                                        "example": "Summer Sale - 50% Off"
                                    },
                                    "gbp_offer_start_date": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Offer start, `YYYY-MM-DD HH:MM:SS` in the workspace owner's timezone. Stored as sent without a check; the publisher reads the date and the time from it, so a date alone means midnight and a value that is not a date makes the offer fail on Google.",
                                        "example": "2026-06-01 00:00:00"
                                    },
                                    "gbp_offer_end_date": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Offer end, `YYYY-MM-DD HH:MM:SS` in the workspace owner's timezone, after the start. Stored as sent without a check, like the start.",
                                        "example": "2026-06-30 23:59:59"
                                    },
                                    "gbp_offer_coupon_code": {
                                        "type": "string",
                                        "description": "Coupon code shown on the offer.",
                                        "example": "SUMMER50"
                                    },
                                    "gbp_offer_terms": {
                                        "type": "string",
                                        "description": "Terms and conditions of the offer.",
                                        "example": "Valid on selected items only"
                                    },
                                    "gbp_redeem_offer_link": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link to redeem the offer.",
                                        "example": "https://example.com/redeem"
                                    },
                                    "yt_title": {
                                        "type": "string",
                                        "description": "Video title. YouTube needs a `video_url`; `message` or `yt_message` is the description.",
                                        "example": "Summer Sale Announcement 2026"
                                    },
                                    "yt_category": {
                                        "type": "string",
                                        "description": "Category name, matched exactly against the list. An unknown or missing name falls back to the default category of the workspace owner's YouTube settings (Entertainment when none is set).",
                                        "enum": [
                                            "Film & Animation",
                                            "Autos & Vehicles",
                                            "Music",
                                            "Pets & Animals",
                                            "Sports",
                                            "Travel & Events",
                                            "Gaming",
                                            "People & Blogs",
                                            "Comedy",
                                            "Entertainment",
                                            "News & Politics",
                                            "Howto & Style",
                                            "Education",
                                            "Science & Technology",
                                            "Nonprofits & Activism"
                                        ],
                                        "example": "Howto & Style"
                                    },
                                    "yt_privacy_status": {
                                        "type": "string",
                                        "description": "Video privacy. Lower-cased and stored as given, so use one of the listed values; an unknown value reaches YouTube and fails there. Nothing is stored when it is omitted and the publisher then uploads the video as `public`.",
                                        "enum": [
                                            "public",
                                            "private",
                                            "unlisted"
                                        ],
                                        "example": "public"
                                    },
                                    "yt_user_tags": {
                                        "type": "string",
                                        "description": "Video tags, comma-separated.",
                                        "example": "summer, sale, deals"
                                    },
                                    "yt_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Custom thumbnail URL for the YouTube video. Public image URL; copied to RecurPost storage unless `host_images_on_recurpost` is off.",
                                        "example": "https://example.com/yt-thumb.jpg"
                                    },
                                    "yt_video_made_for_kids": {
                                        "type": "string",
                                        "description": "Whether the video is made for kids. Only `yes` switches it on.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "no",
                                        "example": "no"
                                    },
                                    "tk_privacy_status": {
                                        "type": "string",
                                        "description": "Who can watch the TikTok video. Case-insensitive, spaces or underscores. Any other value is saved as `Public to Everyone`; omitted leaves it unset. `/api/tiktok_options` lists what the account allows.",
                                        "enum": [
                                            "Public to Everyone",
                                            "Mutual Follow Friends",
                                            "Self Only"
                                        ],
                                        "example": "Public to Everyone"
                                    },
                                    "tk_allow_comments": {
                                        "type": "string",
                                        "description": "Allow comments on the TikTok video. Only `no` switches it off.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_allow_duet": {
                                        "type": "string",
                                        "description": "Allow duets. Only `no` switches it off.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_allow_stitches": {
                                        "type": "string",
                                        "description": "Allow stitches. Only `no` switches it off.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_promote_own_brand": {
                                        "type": "integer",
                                        "description": "Set to `1` to mark the video as promoting your own brand (TikTok's content disclosure).",
                                        "enum": [
                                            0,
                                            1
                                        ],
                                        "default": "0",
                                        "example": 0
                                    },
                                    "tk_promote_other_brand": {
                                        "type": "integer",
                                        "description": "Set to `1` to mark the video as branded content for a third party.",
                                        "enum": [
                                            0,
                                            1
                                        ],
                                        "default": "0",
                                        "example": 0
                                    },
                                    "twitter_thread": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Follow-up tweets posted as a thread under the main tweet on Twitter/X accounts. A JSON array of objects, each with `message` and optionally `image_url` (up to 4) or `video_url` (one, not both). At most 25 items; each item needs a message, an image or a video. Media is hosted like the main post's. Other networks ignore it.",
                                        "example": [
                                            {
                                                "message": "Second tweet with the details.",
                                                "image_url": [
                                                    "https://example.com/detail.jpg"
                                                ]
                                            },
                                            {
                                                "message": "Last one: link in bio."
                                            }
                                        ]
                                    }
                                },
                                "required": [
                                    "id",
                                    "message"
                                ],
                                "example": {
                                    "id": [
                                        "aC3dEf4Gh5==",
                                        "bD4eFg5Hi6=="
                                    ],
                                    "message": "Check out our amazing summer sale! https://example.com/summer-sale"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`One-off added successfully`."
                                        },
                                        "post_data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "Plain integer post id; poll it with `/api/post_status`. The same value appears as `id` in `/api/history_data`."
                                                },
                                                "account_count": {
                                                    "type": "integer",
                                                    "description": "Number of social accounts the post was created for."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "One-off added successfully",
                                    "post_data": {
                                        "id": 901,
                                        "account_count": 2
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (message blank, or id missing / not decryptable.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nimage_url takes at most 20 images. (More than 20 image URLs.)\n\nalt_text entries may have at most 1000 characters. (An alt_text entry is longer than 1000 characters.)\n\nin_location_name is required with in_location_id; both come from instagram_locations. (in_location_id without in_location_name.)\n\nin_collaborators takes at most 3 usernames. (More than 3 collaborators.)\n\nin_reel_tags needs a video_url. (in_reel_tags sent on a post without a video.)\n\nin_image_tags entries need username, x and y between 0 and 1, and image as a position in image_url. (An in_image_tags entry is malformed or points past the last image.)\n\nin_audio_id needs in_post_type reel with a video_url, in_audio_account_id (the account instagram_audio_search ran for), in_audio_type music or original_sound, and volumes from 0 to 100. (in_audio_id sent off a reel, without a video, without a decryptable in_audio_account_id, with an unknown in_audio_type, or with a volume outside 0 to 100.)\n\nin_trial_reel is manual or performance, on in_post_type reel only. (in_trial_reel sent off a reel or with another value.)\n\nin_product_tags entries need account_id, product_id (from instagram_products), image as a position in image_url, and x and y between 0 and 1. (An in_product_tags entry is malformed, points past the last image, or has coordinates outside 0..1.)\n\nin_reel_product_tags entries need account_id and product_id, on in_post_type reel only. (An in_reel_product_tags entry is malformed or the post is not a reel.)\n\nfb_mentions holds page ids from mention_search, as a list or as {page_id, name} items. (An fb_mentions entry is not an all-digit page id.)\n\nfb_mentions takes at most 10 pages. (More than 10 mentions.)\n\nfb_background_id takes a background id from facebook_backgrounds, on a post without image_url or video_url. (fb_background_id is sent with media, or is not a plain id.)\n\nmedia_order may only hold the URLs given in image_url and video_url. (media_order names a URL that is not in the post.)\n\ntwitter_thread takes at most 25 further tweets. (More than 25 thread items.)\n\ntwitter_thread item N needs a message, image_url or video_url. (A thread item is empty or not an object.)\n\ntwitter_thread item N may carry up to 4 images or one video, not both. (A thread item has more than 4 images or images together with a video.)\n\nschedule_date_time must be a datetime like 2026-10-20T09:30:00+05:30. (schedule_date_time does not parse.)\n\n<reason from the first failed account> (The post could not be created on an account (for example an expired token); the first account's reason, else the app's message, is relayed.)\n\n<prefix>_image_url / <prefix>_video_url must leave <network> at least one image or a video. (A per-network media field is sent empty.)\n\nyt_image_url is not accepted; YouTube takes yt_video_url only. (Images sent for YouTube.)\n\n<prefix>_image_url and <prefix>_video_url cannot be combined; only Instagram and Threads take images and a video together. (Images and a video for one network other than Instagram or Threads.)\n\n<prefix>_image_url takes at most <n> images for <network>. (More images than that network allows. Instagram and Threads count images and video together and answer \"_image_url and _video_url take at most  media items together for .\")\n\n<prefix>_media_order may only hold the URLs given in <prefix>_image_url and <prefix>_video_url. (A per-network order names a URL outside that network's own media.)\n\n<prefix>_alt_text entries may have at most 1000 characters. (A per-network alt text entry is longer than 1000 characters.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (One of the ids is not a social account of the workspace owner.)\n\nYou have reached your post limit for the selected date. <plan upgrade sentence> to schedule more posts. (The workspace owner's one-off post limit for that day is used up; any other refusal of the limit check also comes back as 403 with the app's text.)\n\nYou are not allowed to upload video file in your current plan. Please upgrade your RecurPost plan. (video_url sent while the workspace owner is on a free plan.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not one of your workspaces or your membership is not active.)\n\nThis social account is not part of the selected workspace. (An account is the owner's but not in the named workspace_id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Media URL is not allowed: <url>. Please supply a publicly reachable http or https URL. (An image_url, video_url, thumbnail, ln_document thread or per-network media URL is not http/https or its host resolves to a private, loopback or reserved address.)\n\nOops! You need to schedule your update for a time in the future! (schedule_date_time is in the past.)\n\nInvalid url parameter supplied (url (or the first link in the text) is not a valid public URL.)\n\nURL is not a video (detected content type: <type>). Please supply a valid video URL. (video_url answers a non-video content type.)\n\nInvalid video format (detected: <type>). Supported formats: mp4, mov (video_url is neither mp4 nor mov by extension or content type.)\n\nThe media URL could not be downloaded. (video_url or ln_document could not be read.)\n\nFailed to upload video. The URL was reachable but the file could not be processed. (The downloaded video was refused by storage (size over 2 GB, unreadable file).)\n\nURL is not an image (detected content type: <type>). Please supply a valid image URL. (An image_url answers a non-image content type.)\n\nInvalid image url parameter supplied. The URL did not return a recognizable image. (An image_url could not be read as an image.)\n\nFailed to upload image. The URL was reachable but the file could not be processed. (The image could not be stored.)\n\nInvalid <param> parameter supplied. The URL did not return a recognizable image. (fb_thumb, in_thumb, ln_thumb or yt_thumb is not an image (only checked on video posts with hosting on).)\n\nFailed to upload <param>. The URL was reachable but the file could not be processed. (A thumbnail could not be stored.)\n\nThe uploaded file at <url> is missing or is not a <image|video> (detected <type>). (A media_upload_url URL was never PUT to, or was PUT with the wrong Content-Type.)\n\nFiles are limited to 2 GB. (A media_upload_url object is larger than 2 GB.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Content validation failed! (The app's content validator refused one or more network tabs (text too long, media that the network does not accept, a reel without video, ...). The body carries `error_details`, an object keyed by network with the reason.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/media_upload_url": {
            "post": {
                "tags": [
                    "Media"
                ],
                "summary": "Get a signed URL to upload an image or video directly to RecurPost storage.",
                "description": "Answers a presigned PUT URL for one file in your own media folder on RecurPost storage, plus the public `media_url` that file will have. Use it to avoid hosting media yourself or to send files that are not reachable from the internet. The flow has three steps:\n- Call this endpoint with the `filename` (its extension picks the type and the image or video folder) and, optionally, the `size` in bytes. You get `upload.url`, `upload.content_type` and `media_url`.\n- Send the raw file bytes with an HTTP `PUT` to `upload.url` within `upload.expires_in` seconds (15 minutes). Set the `Content-Type` header to `upload.content_type`; no Authorization header, no form encoding, no other fields. A `200` from storage means the file is stored.\n- Use `media_url` as `image_url`, `video_url` or a thumbnail on `/api/post_content`, `/api/draft_save`, `/api/add_content_in_library` or `/api/library_content_update`. Those calls recognise the URL as yours and use it as it is, without downloading it again.\n\nThe stored object is checked when it is first used in a post: it must exist, answer a `Content-Type` that starts with `image/` or `video/` matching the field it is used in, and be at most 2 GB. Nothing is validated at upload time, so a PUT with the wrong `Content-Type` (or none) fails later with 415 on the post call.\n\nSet the Content-Type on the PUT: Storage saves whatever header you send. The post calls later refuse an object whose stored type does not start with `image/` (for `image_url` and thumbnails) or `video/` (for `video_url`) with 415 `The uploaded file at ... is missing or is not a ...`. Send exactly `upload.content_type`.\n\nOne URL per file: Each call signs one new object key. Request a new URL for every file and for every retry after the 15 minutes have passed; the `media_url` of an unused URL simply never resolves.\n\nCounts as your media: The file lands in your account's media folder, is owned by you (not the workspace) and is not re-downloaded or re-encoded by the post calls. Images uploaded this way are used as given even when `host_images_on_recurpost` is on; a video gets the default poster image unless you pass a custom cover.\n\nNot for LinkedIn documents: `ln_document` is always downloaded and typed by its bytes; upload documents to a public URL of your own instead.",
                "operationId": "media_upload_url",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "filename": {
                                        "type": "string",
                                        "description": "Name of the file you will upload. Only the extension is used: `jpg`, `jpeg`, `png`, `gif`, `webp` go to your image folder; `mp4`, `mov` go to your video folder. Case-insensitive. The stored object gets a generated name, not this one.",
                                        "example": "summer-sale.jpg"
                                    },
                                    "size": {
                                        "type": "integer",
                                        "description": "File size in bytes, when known. A value over 2 GB (2147483648) is refused up front; the size is not checked against the actual PUT.",
                                        "example": 348211
                                    }
                                },
                                "required": [
                                    "filename"
                                ],
                                "example": {
                                    "filename": "summer-sale.jpg"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "upload": {
                                            "type": "object",
                                            "properties": {
                                                "url": {
                                                    "type": "string",
                                                    "format": "uri",
                                                    "description": "Presigned storage URL to PUT the file bytes to. Signed for the object key only; it carries the credentials in its query string."
                                                },
                                                "method": {
                                                    "type": "string",
                                                    "description": "Always `PUT`."
                                                },
                                                "content_type": {
                                                    "type": "string",
                                                    "description": "The `Content-Type` header to send with the PUT: `image/jpeg`, `image/png`, `image/gif`, `image/webp`, `video/mp4` or `video/quicktime`."
                                                },
                                                "expires_in": {
                                                    "type": "integer",
                                                    "description": "Seconds the upload URL stays valid, always 900."
                                                }
                                            }
                                        },
                                        "media_url": {
                                            "type": "string",
                                            "format": "uri",
                                            "description": "Public CDN URL the file will have once uploaded. Pass it to the post and library calls as `image_url`, `video_url` or a thumbnail."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "upload": {
                                        "url": "https://recurpost-media.s3.amazonaws.com/user_12345/images/1761130800_6718f2a1b3c4d.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Expires=900&X-Amz-Signature=...",
                                        "method": "PUT",
                                        "content_type": "image/jpeg",
                                        "expires_in": 900
                                    },
                                    "media_url": "https://media.recurpost.com/user_12345/images/1761130800_6718f2a1b3c4d.jpg"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "filename must end in jpg, jpeg, png, gif, webp, mp4 or mov. (filename missing or with another extension.)\n\nFiles are limited to 2 GB. (size is larger than 2 GB.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The upload URL could not be created. Please try again. (Storage did not sign the request.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/media_list": {
            "post": {
                "tags": [
                    "Media"
                ],
                "summary": "The images, GIFs and videos already used in the owner's posts, newest first.",
                "description": "Pages through the media the workspace owner has already used in posts, 50 a page, newest first. `types` narrows to images, GIFs or videos and `search` matches the text of the posts the media was used in. Every item carries a URL you can send again as `image_url` or `video_url` in `/api/post_content` or `/api/add_content_in_library`; media already on RecurPost storage is not downloaded again.\nThe app lists the owner's media across all of their workspaces, so `workspace_id` only picks the owner here.",
                "operationId": "media_list",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "page": {
                                        "type": "integer",
                                        "description": "Page, from 1; 50 items a page. There is no total: an empty page means the end.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "types": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Kinds to list: any of `image`, `gif`, `video`, as an array or a comma-separated string. All three when omitted.",
                                        "default": "image,gif,video",
                                        "example": [
                                            "image",
                                            "video"
                                        ]
                                    },
                                    "search": {
                                        "type": "string",
                                        "description": "Text to match against the posts the media was used in.",
                                        "example": "sale"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`"
                                        },
                                        "page": {
                                            "type": "integer",
                                            "description": "The page returned."
                                        },
                                        "per_page": {
                                            "type": "integer",
                                            "description": "Always 50."
                                        },
                                        "items": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "type": {
                                                        "type": "string",
                                                        "description": "image, gif or video."
                                                    },
                                                    "url": {
                                                        "type": "string",
                                                        "description": "The media URL on RecurPost storage."
                                                    },
                                                    "thumbnail": {
                                                        "type": "string",
                                                        "description": "For a video its cover image; for an image or GIF the same URL as `url`."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "page": 1,
                                    "per_page": 50,
                                    "items": [
                                        {
                                            "type": "image",
                                            "url": "https://cdn.example.com/u/1/sale.jpg",
                                            "thumbnail": "https://cdn.example.com/u/1/sale.jpg"
                                        },
                                        {
                                            "type": "video",
                                            "url": "https://cdn.example.com/u/1/promo.mp4",
                                            "thumbnail": "https://cdn.example.com/u/1/promo_thumb.jpg"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "types may hold image, gif and video. (types holds another word.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nThe media could not be read. (The app failed without a message; a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/draft_list": {
            "post": {
                "tags": [
                    "Drafts"
                ],
                "summary": "List the drafts of a workspace with the accounts each one targets.",
                "description": "Returns every draft of the workspace, oldest planned time first, with the social accounts it is saved for. `account_ids` narrows the list to drafts that include at least one of those accounts. The whole list is read and then paged, so `total_drafts` is the count of the full list.\n\nTwo clocks: The draft-level `planned_for` is shown in the workspace owner's timezone, each account's `planned_for` in that account's timezone. A draft saved for accounts in different zones shows different wall-clock values that stand for the same instant.",
                "operationId": "draft_list",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "account_ids": {
                                        "type": "string",
                                        "description": "Encrypted social account ids from `/api/social_account_list`, one id, a comma-separated string or an array. Only drafts saved for one of these accounts are returned. Every id must belong to the workspace owner.",
                                        "example": "aB3dE5fG7h==,kL9mN1oP3q=="
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Page number, starting at 1.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "per_page": {
                                        "type": "integer",
                                        "description": "Drafts per page, 1 to 200.",
                                        "default": "50",
                                        "example": 50
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "total_drafts": {
                                            "type": "integer",
                                            "description": "Number of drafts in the workspace after the `account_ids` filter, across all pages."
                                        },
                                        "page": {
                                            "type": "integer",
                                            "description": "The page returned."
                                        },
                                        "per_page": {
                                            "type": "integer",
                                            "description": "The page size used."
                                        },
                                        "has_more": {
                                            "type": "boolean",
                                            "description": "`true` when a later page exists."
                                        },
                                        "drafts": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain numeric draft id. Pass it as `draft_id` to `/api/draft_save`, `/api/draft_schedule` and `/api/draft_delete`; it is the same id `/api/post_status` reads."
                                                    },
                                                    "message": {
                                                        "type": "string",
                                                        "description": "Text of the original tab."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Link preview title, blank when the draft has no link."
                                                    },
                                                    "description": {
                                                        "type": "string",
                                                        "description": "Link preview description."
                                                    },
                                                    "url": {
                                                        "type": "string",
                                                        "description": "Link attached to the draft."
                                                    },
                                                    "image_url": {
                                                        "type": "string",
                                                        "description": "First image, the link preview image, or the video thumbnail; blank for a text draft."
                                                    },
                                                    "video_url": {
                                                        "type": "string",
                                                        "description": "Hosted video URL, blank when there is none."
                                                    },
                                                    "library": {
                                                        "type": "string",
                                                        "description": "Name of the library the draft came from, blank for a direct post."
                                                    },
                                                    "planned_for": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "Intended time in the workspace owner's timezone. When no time was given when saving, this is the moment the draft was saved."
                                                    },
                                                    "accounts": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "object",
                                                            "properties": {
                                                                "id": {
                                                                    "type": "string",
                                                                    "description": "Encrypted social account id."
                                                                },
                                                                "name": {
                                                                    "type": "string",
                                                                    "description": "Account display name."
                                                                },
                                                                "network": {
                                                                    "type": "string",
                                                                    "description": "`facebook`, `twitter`, `linkedin`, `instagram`, `pinterest`, `google_my_business`, `tiktok`, `youtube`, `threads` or `bluesky`."
                                                                },
                                                                "status": {
                                                                    "type": "string",
                                                                    "description": "`active`, `paused` or `needs_reconnection`."
                                                                },
                                                                "planned_for": {
                                                                    "type": "string",
                                                                    "format": "date-time",
                                                                    "description": "Intended time in that account's own timezone (the owner's when the account has none)."
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "total_drafts": 1,
                                    "page": 1,
                                    "per_page": 50,
                                    "has_more": false,
                                    "drafts": [
                                        {
                                            "id": 48213,
                                            "message": "Our autumn collection drops next week.",
                                            "title": "",
                                            "description": "",
                                            "url": "",
                                            "image_url": "https://media.recurpost.com/u/1021/images/autumn.jpg",
                                            "video_url": "",
                                            "library": "",
                                            "planned_for": "2026-11-03 10:00:00",
                                            "accounts": [
                                                {
                                                    "id": "nX2k9Qp7Lw==",
                                                    "name": "Acme Store",
                                                    "network": "facebook",
                                                    "status": "active",
                                                    "planned_for": "2026-11-03 10:00:00"
                                                },
                                                {
                                                    "id": "kL9mN1oP3q==",
                                                    "name": "@acmestore",
                                                    "network": "instagram",
                                                    "status": "active",
                                                    "planned_for": "2026-11-03 15:30:00"
                                                }
                                            ]
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "account_ids holds an invalid id. (One of the account_ids values does not decrypt to an id.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (An account in account_ids does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (You are not the owner or an active member of that workspace.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and an account in account_ids sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/draft_save": {
            "post": {
                "tags": [
                    "Drafts"
                ],
                "summary": "Save a new draft, or replace the content and accounts of an existing one.",
                "description": "Saves a post as a draft for one or several social accounts. Takes the same content fields as `/api/post_content`: the text, media, link, a per-network message and the network options listed below. Media URLs are downloaded and copied to RecurPost storage during the call, so expect it to take a few seconds for videos.\nSend `draft_id` to replace an existing draft in place: its text, media, options and account list are overwritten with what you send. Only a post that is still a draft can be replaced; a scheduled or published post answers 409.\nThe content is validated per network before anything is written. A failure answers 422 with `error_details` keyed by network and nothing is saved.\n\nReplacing is a full overwrite: With `draft_id` the draft's text, media, per-network options and account list are all replaced by the request. Fields you leave out are cleared, not kept. The id stays the same.\n\nMedia is fetched during the call: Images, videos, custom thumbnails and LinkedIn documents are downloaded and copied to RecurPost storage while the request runs. Upload large files first with `/api/media_upload_url` and pass the returned URL; those are stored once and only checked here.\n\nPinterest destination link: When one of the accounts is a Pinterest board, `url` (or the first link in the text) is stored as the pin's destination link rather than as a link preview.\n\nPer-network media: A network can post media of its own: `<prefix>_image_url` and `<prefix>_video_url` (`fb_`, `tw_`, `ln_`, `in_`, `gmb_`, `pi_`, `yt_`, `tk_`, `th_`, `bs_`) replace `image_url` / `video_url` on that network only and mark its tab as customised. Each network keeps its own cap (Facebook 15, Twitter/X 4, LinkedIn 20, Instagram 10 in all, Google Business 1, Pinterest 1, TikTok 10, Threads 20 in all, Bluesky 4); only Instagram and Threads combine images with a video, ordered by `in_media_order` / `th_media_order`; YouTube takes `yt_video_url` only. A URL named by several networks is downloaded once. Covers (`fb_thumb` and the others) apply to whichever video that network ends up with; `in_image_tags` and `in_product_tags` positions count in `in_image_url` when Instagram has its own images. Removing all media from one network is not possible: an empty override answers 400.",
                "operationId": "draft_save",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted social account id(s) from `/api/social_account_list`: one id, a comma-separated string or an array. Every account must belong to the workspace owner.",
                                        "example": "nX2k9Qp7Lw==,kL9mN1oP3q=="
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "Post text for every network. Required unless `image_url` or `video_url` is sent. Windows line endings are normalised to `\\n`.",
                                        "example": "Our autumn collection drops next week."
                                    },
                                    "draft_id": {
                                        "type": "integer",
                                        "description": "Plain numeric id of an existing draft (from `/api/draft_list`). When sent, that draft is replaced instead of a new one being created.",
                                        "example": 48213
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "schedule_date_time": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Intended publish time, `YYYY-MM-DD HH:MM:SS`, read as the wall-clock time in each account's timezone. It is recorded on the draft only; the post is not scheduled until `/api/draft_schedule` is called. A value that does not parse is ignored. When omitted the save time is recorded. `shedule_date_time` is accepted as a legacy alias.",
                                        "example": "2026-11-03 10:00:00"
                                    },
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link to attach. On a text post it becomes the link preview; when omitted the first URL found in `message` is used. On a Pinterest account it is the pin's destination link. Must be a public http or https address.",
                                        "example": "https://example.com/autumn"
                                    },
                                    "image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Public image URLs, up to 20, posted in the order given. Send an array even for one image. URLs returned by `/api/media_upload_url` are used as they are; other URLs are downloaded and re-hosted.",
                                        "example": [
                                            "https://example.com/autumn-1.jpg",
                                            "https://example.com/autumn-2.jpg"
                                        ]
                                    },
                                    "video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public URL of an mp4 or mov video (Google Drive share links are accepted). Combined with `image_url` it makes a mixed carousel. Video posts are not available on free plans.",
                                        "example": "https://example.com/autumn.mp4"
                                    },
                                    "media_order": {
                                        "type": "array",
                                        "items": [],
                                        "description": "For a mixed image and video post: the original `image_url` and `video_url` values in the order the slides should appear. Any URL not listed follows, video first.",
                                        "example": [
                                            "https://example.com/autumn.mp4",
                                            "https://example.com/autumn-1.jpg"
                                        ]
                                    },
                                    "host_images_on_recurpost": {
                                        "type": "boolean",
                                        "description": "Copy images and custom thumbnails to RecurPost storage (the default). Send `false`, `0` or the form string `\"false\"` to keep your own URLs instead; they must then stay reachable until every post using them has been published.",
                                        "enum": [
                                            true,
                                            false
                                        ],
                                        "default": "true",
                                        "example": true
                                    },
                                    "alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text per image, one string or an array in `image_url` order, at most 1000 characters each. Applied on Facebook, Twitter/X, LinkedIn, Pinterest, Threads and Bluesky.",
                                        "example": [
                                            "Autumn coat on a wooden hanger"
                                        ]
                                    },
                                    "fb_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Facebook accounts instead of `image_url`, same rules and hosting as `image_url`. At most 15 images on Facebook. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `fb_video_url`.",
                                        "example": [
                                            "https://example.com/fb-square.jpg"
                                        ]
                                    },
                                    "fb_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Facebook accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `fb_image_url`.",
                                        "example": "https://example.com/fb-clip.mp4"
                                    },
                                    "fb_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `fb_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "tw_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Twitter/X accounts instead of `image_url`, same rules and hosting as `image_url`. At most 4 images on Twitter/X. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `tw_video_url`.",
                                        "example": [
                                            "https://example.com/tw-square.jpg"
                                        ]
                                    },
                                    "tw_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Twitter/X accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `tw_image_url`.",
                                        "example": "https://example.com/tw-clip.mp4"
                                    },
                                    "tw_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `tw_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "ln_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for LinkedIn accounts instead of `image_url`, same rules and hosting as `image_url`. At most 20 images on LinkedIn. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `ln_video_url`.",
                                        "example": [
                                            "https://example.com/ln-square.jpg"
                                        ]
                                    },
                                    "ln_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for LinkedIn accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `ln_image_url`.",
                                        "example": "https://example.com/ln-clip.mp4"
                                    },
                                    "ln_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `ln_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "in_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Instagram accounts instead of `image_url`, same rules and hosting as `image_url`. At most 10 media in all, images and video together on Instagram. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. May be combined with `in_video_url` into a carousel; `in_media_order` sets the order.",
                                        "example": [
                                            "https://example.com/in-square.jpg"
                                        ]
                                    },
                                    "in_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Instagram accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. May be combined with `in_image_url` into a carousel.",
                                        "example": "https://example.com/in-clip.mp4"
                                    },
                                    "in_media_order": {
                                        "type": "array",
                                        "items": [],
                                        "description": "The order of Instagram's own media as a list of the URLs given in `in_image_url` and `in_video_url`. Media left out of the list follow, video first. Only read when both are sent. Any other URL answers 400.",
                                        "example": [
                                            "https://example.com/in-clip.mp4",
                                            "https://example.com/in-square.jpg"
                                        ]
                                    },
                                    "gmb_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Google Business accounts instead of `image_url`, same rules and hosting as `image_url`. At most 1 image on Google Business. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `gmb_video_url`.",
                                        "example": [
                                            "https://example.com/gmb-square.jpg"
                                        ]
                                    },
                                    "gmb_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Google Business accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `gmb_image_url`.",
                                        "example": "https://example.com/gmb-clip.mp4"
                                    },
                                    "pi_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Pinterest accounts instead of `image_url`, same rules and hosting as `image_url`. At most 1 image on Pinterest. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `pi_video_url`.",
                                        "example": [
                                            "https://example.com/pi-square.jpg"
                                        ]
                                    },
                                    "pi_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Pinterest accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `pi_image_url`.",
                                        "example": "https://example.com/pi-clip.mp4"
                                    },
                                    "pi_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `pi_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "yt_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for YouTube accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. YouTube takes a video only, so there is no `yt_image_url`.",
                                        "example": "https://example.com/yt-clip.mp4"
                                    },
                                    "tk_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for TikTok accounts instead of `image_url`, same rules and hosting as `image_url`. At most 10 images on TikTok. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `tk_video_url`.",
                                        "example": [
                                            "https://example.com/tk-square.jpg"
                                        ]
                                    },
                                    "tk_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for TikTok accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `tk_image_url`.",
                                        "example": "https://example.com/tk-clip.mp4"
                                    },
                                    "th_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Threads accounts instead of `image_url`, same rules and hosting as `image_url`. At most 20 media in all, images and video together on Threads. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. May be combined with `th_video_url` into a carousel; `th_media_order` sets the order.",
                                        "example": [
                                            "https://example.com/th-square.jpg"
                                        ]
                                    },
                                    "th_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Threads accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. May be combined with `th_image_url` into a carousel.",
                                        "example": "https://example.com/th-clip.mp4"
                                    },
                                    "th_media_order": {
                                        "type": "array",
                                        "items": [],
                                        "description": "The order of Threads's own media as a list of the URLs given in `th_image_url` and `th_video_url`. Media left out of the list follow, video first. Only read when both are sent. Any other URL answers 400.",
                                        "example": [
                                            "https://example.com/th-clip.mp4",
                                            "https://example.com/th-square.jpg"
                                        ]
                                    },
                                    "th_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `th_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "bs_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Bluesky accounts instead of `image_url`, same rules and hosting as `image_url`. At most 4 images on Bluesky. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `bs_video_url`.",
                                        "example": [
                                            "https://example.com/bs-square.jpg"
                                        ]
                                    },
                                    "bs_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Bluesky accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `bs_image_url`.",
                                        "example": "https://example.com/bs-clip.mp4"
                                    },
                                    "bs_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `bs_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "first_comment": {
                                        "type": "string",
                                        "description": "Comment posted right after the post on Facebook pages, LinkedIn and Instagram feed posts, often used for hashtags. The network-specific `fb_first_comment`, `ln_first_comment` and `in_first_comment` override it.",
                                        "example": "#autumn #newcollection"
                                    },
                                    "fb_message": {
                                        "type": "string",
                                        "description": "Facebook text that replaces `message`. The same applies to `tw_message`, `ln_message`, `in_message`, `gmb_message`, `pi_message`, `yt_message`, `tk_message`, `th_message` and `bs_message`. On a text post the first URL in the network text becomes that network's link preview.",
                                        "example": "Autumn is here. See the full collection on our page."
                                    },
                                    "tw_message": {
                                        "type": "string",
                                        "description": "Twitter/X text that replaces `message`.",
                                        "example": "Autumn drop next week."
                                    },
                                    "ln_message": {
                                        "type": "string",
                                        "description": "LinkedIn text that replaces `message`.",
                                        "example": "Our autumn collection launches next week."
                                    },
                                    "in_message": {
                                        "type": "string",
                                        "description": "Instagram caption that replaces `message`.",
                                        "example": "Autumn drop next week."
                                    },
                                    "gmb_message": {
                                        "type": "string",
                                        "description": "Google Business text that replaces `message`.",
                                        "example": "Visit the store for the new autumn collection."
                                    },
                                    "pi_message": {
                                        "type": "string",
                                        "description": "Pinterest description that replaces `message`.",
                                        "example": "Autumn collection 2026"
                                    },
                                    "yt_message": {
                                        "type": "string",
                                        "description": "YouTube description that replaces `message`.",
                                        "example": "Watch the autumn collection reveal."
                                    },
                                    "tk_message": {
                                        "type": "string",
                                        "description": "TikTok caption that replaces `message`.",
                                        "example": "Autumn drop next week."
                                    },
                                    "th_message": {
                                        "type": "string",
                                        "description": "Threads text that replaces `message`.",
                                        "example": "Autumn drop next week."
                                    },
                                    "bs_message": {
                                        "type": "string",
                                        "description": "Bluesky text that replaces `message`.",
                                        "example": "Autumn drop next week."
                                    },
                                    "twitter_thread": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Follow-up tweets posted as a thread under the Twitter/X post, up to 25 objects of `message`, `image_url` (array, up to 4) and `video_url`. Each item needs text or media and may carry images or one video, not both. Thread media is hosted like the main post's.",
                                        "example": [
                                            {
                                                "message": "Sizes run from XS to XXL."
                                            },
                                            {
                                                "message": "Pre-orders open Monday.",
                                                "image_url": [
                                                    "https://example.com/preorder.jpg"
                                                ]
                                            }
                                        ]
                                    },
                                    "fb_post_type": {
                                        "type": "string",
                                        "description": "Facebook post type.",
                                        "enum": [
                                            "feed",
                                            "reel",
                                            "story"
                                        ],
                                        "default": "feed",
                                        "example": "feed"
                                    },
                                    "fb_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public image used as the Facebook cover of `video_url`. Ignored when the post has no video.",
                                        "example": "https://example.com/cover-fb.jpg"
                                    },
                                    "fb_first_comment": {
                                        "type": "string",
                                        "description": "Facebook first comment, overrides `first_comment`.",
                                        "example": "#autumn #facebook"
                                    },
                                    "ln_document": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public URL of a PDF, PPT, PPTX, DOC or DOCX posted as a LinkedIn document (carousel). The file is downloaded and stored during the call; the LinkedIn tab then becomes a document post.",
                                        "example": "https://example.com/autumn-lookbook.pdf"
                                    },
                                    "ln_document_title": {
                                        "type": "string",
                                        "description": "Title shown on the LinkedIn document. Defaults to the file name without extension.",
                                        "example": "Autumn Lookbook 2026"
                                    },
                                    "ln_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public image used as the LinkedIn cover of `video_url`. Ignored when the post has no video.",
                                        "example": "https://example.com/cover-ln.jpg"
                                    },
                                    "ln_first_comment": {
                                        "type": "string",
                                        "description": "LinkedIn first comment, overrides `first_comment`.",
                                        "example": "#autumn #linkedin"
                                    },
                                    "in_post_type": {
                                        "type": "string",
                                        "description": "Instagram post type.",
                                        "enum": [
                                            "feed",
                                            "story",
                                            "reel"
                                        ],
                                        "default": "feed",
                                        "example": "feed"
                                    },
                                    "in_reel_share_in_feed": {
                                        "type": "string",
                                        "description": "Also show a reel in the feed. Only read when `in_post_type` is `reel`.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "in_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public image used as the reel cover. Only read when `in_post_type` is `reel` and the post has a video.",
                                        "example": "https://example.com/cover-in.jpg"
                                    },
                                    "in_first_comment": {
                                        "type": "string",
                                        "description": "Instagram first comment (feed posts only), overrides `first_comment`.",
                                        "example": "#autumn #instagram"
                                    },
                                    "in_location_id": {
                                        "type": "string",
                                        "description": "Instagram location id from `/api/instagram_locations`. Needs `in_location_name`.",
                                        "example": "212988663"
                                    },
                                    "in_location_name": {
                                        "type": "string",
                                        "description": "Location name as returned by `/api/instagram_locations`. Required with `in_location_id`.",
                                        "example": "Amsterdam, Netherlands"
                                    },
                                    "in_location_city": {
                                        "type": "string",
                                        "description": "Location city, as returned by `/api/instagram_locations`.",
                                        "example": "Amsterdam"
                                    },
                                    "in_location_country": {
                                        "type": "string",
                                        "description": "Location country, as returned by `/api/instagram_locations`.",
                                        "example": "Netherlands"
                                    },
                                    "in_image_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "People tagged on Instagram feed images: objects of `image` (1-based position in `image_url`), `username` and the tag position `x` and `y` as fractions between 0 and 1.",
                                        "example": [
                                            {
                                                "image": 1,
                                                "username": "acmestore",
                                                "x": 0.5,
                                                "y": 0.4
                                            }
                                        ]
                                    },
                                    "in_reel_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Usernames tagged on an Instagram reel; an array or a comma-separated string. Needs `video_url`.",
                                        "example": [
                                            "acmestore"
                                        ]
                                    },
                                    "in_collaborators": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Instagram collaborator usernames, at most 3; an array or a comma-separated string.",
                                        "example": [
                                            "acmestudio"
                                        ]
                                    },
                                    "pi_title": {
                                        "type": "string",
                                        "description": "Pinterest pin title.",
                                        "example": "Autumn Collection 2026"
                                    },
                                    "gbp_cta": {
                                        "type": "string",
                                        "description": "Google Business call-to-action button, matched case-insensitively. A link post with no CTA gets `Learn more` pointing at the link.",
                                        "enum": [
                                            "None",
                                            "Learn more",
                                            "Sign up",
                                            "Buy",
                                            "Order online",
                                            "Book",
                                            "Call now",
                                            "Offer"
                                        ],
                                        "default": "None",
                                        "example": "Learn more"
                                    },
                                    "gbp_cta_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link behind the CTA button. Not used for `Call now`; for `Offer` it doubles as the redeem link when `gbp_redeem_offer_link` is blank.",
                                        "example": "https://example.com/autumn"
                                    },
                                    "gbp_offer_title": {
                                        "type": "string",
                                        "description": "Offer title, when `gbp_cta` is `Offer`.",
                                        "example": "20% off coats"
                                    },
                                    "gbp_offer_start_date": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Offer start, `YYYY-MM-DD HH:MM:SS`.",
                                        "example": "2026-11-03 00:00:00"
                                    },
                                    "gbp_offer_end_date": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Offer end, `YYYY-MM-DD HH:MM:SS`.",
                                        "example": "2026-11-30 23:59:59"
                                    },
                                    "gbp_offer_coupon_code": {
                                        "type": "string",
                                        "description": "Coupon code shown with the offer.",
                                        "example": "AUTUMN20"
                                    },
                                    "gbp_offer_terms": {
                                        "type": "string",
                                        "description": "Offer terms and conditions.",
                                        "example": "Valid in store until 30 November."
                                    },
                                    "gbp_redeem_offer_link": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link to redeem the offer.",
                                        "example": "https://example.com/redeem"
                                    },
                                    "yt_title": {
                                        "type": "string",
                                        "description": "YouTube video title.",
                                        "example": "Autumn Collection Reveal"
                                    },
                                    "yt_category": {
                                        "type": "string",
                                        "description": "YouTube category name. Unknown names fall back to the owner's default category set in RecurPost.",
                                        "enum": [
                                            "Film & Animation",
                                            "Autos & Vehicles",
                                            "Music",
                                            "Pets & Animals",
                                            "Sports",
                                            "Travel & Events",
                                            "Gaming",
                                            "People & Blogs",
                                            "Comedy",
                                            "Entertainment",
                                            "News & Politics",
                                            "Howto & Style",
                                            "Education",
                                            "Science & Technology",
                                            "Nonprofits & Activism"
                                        ],
                                        "example": "Howto & Style"
                                    },
                                    "yt_privacy_status": {
                                        "type": "string",
                                        "description": "YouTube visibility, case-insensitive.",
                                        "enum": [
                                            "public",
                                            "private",
                                            "unlisted"
                                        ],
                                        "default": "public",
                                        "example": "public"
                                    },
                                    "yt_user_tags": {
                                        "type": "string",
                                        "description": "YouTube tags, comma-separated.",
                                        "example": "autumn, fashion, lookbook"
                                    },
                                    "yt_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public image used as the YouTube thumbnail.",
                                        "example": "https://example.com/cover-yt.jpg"
                                    },
                                    "yt_video_made_for_kids": {
                                        "type": "string",
                                        "description": "Mark the video as made for kids.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "no",
                                        "example": "no"
                                    },
                                    "tk_privacy_status": {
                                        "type": "string",
                                        "description": "TikTok visibility, matched case-insensitively with spaces or underscores. Unknown values fall back to `Public to Everyone`.",
                                        "enum": [
                                            "Public to Everyone",
                                            "Mutual Follow Friends",
                                            "Self Only"
                                        ],
                                        "default": "Public to Everyone",
                                        "example": "Public to Everyone"
                                    },
                                    "tk_allow_comments": {
                                        "type": "string",
                                        "description": "Allow comments on the TikTok post.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_allow_duet": {
                                        "type": "string",
                                        "description": "Allow duets.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_allow_stitches": {
                                        "type": "string",
                                        "description": "Allow stitches.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_promote_own_brand": {
                                        "type": "integer",
                                        "description": "Send `1` to label the TikTok post as promoting your own brand.",
                                        "enum": [
                                            0,
                                            1
                                        ],
                                        "default": "0",
                                        "example": 0
                                    },
                                    "tk_promote_other_brand": {
                                        "type": "integer",
                                        "description": "Send `1` to label the TikTok post as a paid partnership (promoting another brand).",
                                        "enum": [
                                            0,
                                            1
                                        ],
                                        "default": "0",
                                        "example": 0
                                    }
                                },
                                "required": [
                                    "id",
                                    "message"
                                ],
                                "example": {
                                    "id": "nX2k9Qp7Lw==,kL9mN1oP3q==",
                                    "message": "Our autumn collection drops next week."
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Draft saved.` for a new draft, `Draft updated.` when `draft_id` was sent."
                                        },
                                        "draft_id": {
                                            "type": "integer",
                                            "description": "Plain numeric id of the draft. Use it with `/api/draft_schedule` and `/api/draft_delete`."
                                        },
                                        "account_count": {
                                            "type": "integer",
                                            "description": "Number of social accounts the draft is saved for."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Draft saved.",
                                    "draft_id": 48213,
                                    "account_count": 2
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or invalid, or there is no message and no image_url or video_url.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nimage_url takes at most 20 images. (More than 20 image URLs were sent.)\n\nalt_text entries may have at most 1000 characters. (An alt_text value is longer than 1000 characters.)\n\nin_location_name is required with in_location_id; both come from instagram_locations. (in_location_id was sent without in_location_name.)\n\nin_collaborators takes at most 3 usernames. (More than 3 collaborator usernames were sent.)\n\nin_reel_tags needs a video_url. (in_reel_tags was sent on a post without a video.)\n\nin_image_tags entries need username, x and y between 0 and 1, and image as a position in image_url. (An in_image_tags item is malformed or points outside image_url.)\n\nmedia_order may only hold the URLs given in image_url and video_url. (media_order lists a URL that is not in image_url or video_url.)\n\ntwitter_thread takes at most 25 further tweets. (More than 25 thread items were sent.)\n\ntwitter_thread item N needs a message, image_url or video_url. (A thread item is empty.)\n\ntwitter_thread item N may carry up to 4 images or one video, not both. (A thread item has more than 4 images, or images and a video.)\n\nThe draft could not be saved. (The save failed inside the app without a message. When the app returns its own error text that text is relayed instead, with a 500 when it sent no status.)\n\n<prefix>_image_url / <prefix>_video_url must leave <network> at least one image or a video. (A per-network media field is sent empty.)\n\nyt_image_url is not accepted; YouTube takes yt_video_url only. (Images sent for YouTube.)\n\n<prefix>_image_url and <prefix>_video_url cannot be combined; only Instagram and Threads take images and a video together. (Images and a video for one network other than Instagram or Threads.)\n\n<prefix>_image_url takes at most <n> images for <network>. (More images than that network allows. Instagram and Threads count images and video together and answer \"_image_url and _video_url take at most  media items together for .\")\n\n<prefix>_media_order may only hold the URLs given in <prefix>_image_url and <prefix>_video_url. (A per-network order names a URL outside that network's own media.)\n\n<prefix>_alt_text entries may have at most 1000 characters. (A per-network alt text entry is longer than 1000 characters.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (An account in id, or the post named by draft_id, does not belong to the workspace owner.)\n\nYou are not allowed to upload video file in your current plan. Please upgrade your RecurPost plan. (video_url was sent and the workspace owner is on a free plan.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (You are not the owner or an active member of that workspace.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and an account in id sits in another workspace.)\n\nDraft not found. (draft_id names a post that has no account rows.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This post is not a draft. (draft_id names a post that is already scheduled, published or deleted.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Media URL is not allowed: ... Please supply a publicly reachable http or https URL. (An image, video, thumbnail or document URL is not a public http or https address.)\n\nInvalid url parameter supplied (url, or the link found in message, is not a valid public URL.)\n\nURL is not a video (detected content type: ...). Please supply a valid video URL. (video_url does not serve a video content type.)\n\nInvalid video format (detected: ...). Supported formats: mp4, mov (The video is neither mp4 nor mov.)\n\nThe media URL could not be downloaded. (A video or LinkedIn document URL could not be read.)\n\nFailed to upload video. The URL was reachable but the file could not be processed. (The downloaded video could not be stored.)\n\nURL is not an image (detected content type: ...). Please supply a valid image URL. (An image_url entry serves something other than an image.)\n\nInvalid image url parameter supplied. The URL did not return a recognizable image. (An image_url entry could not be read as an image.)\n\nFailed to upload image. The URL was reachable but the file could not be processed. (The downloaded image could not be stored.)\n\nInvalid fb_thumb parameter supplied. The URL did not return a recognizable image. (A custom thumbnail (fb_thumb, in_thumb, ln_thumb, yt_thumb) is not an image; the message names the parameter.)\n\nFailed to upload fb_thumb. The URL was reachable but the file could not be processed. (A custom thumbnail could not be stored; the message names the parameter.)\n\nThe uploaded file at ... is missing or is not a video (detected ...). (A URL from /api/media_upload_url points at a missing file or one of the wrong type.)\n\nFiles are limited to 2 GB. (A file uploaded through /api/media_upload_url is larger than 2 GB.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Content validation failed! (A network tab fails validation. error_details maps the network (original, facebook, instagram, ...) to the reason, such as Please enter text message!, No images found!, Invalid image supplied!, Please upload video!, Invalid URL link supplied! or A mixed post needs a video and at least one more image or video!. Nothing is saved.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/draft_schedule": {
            "post": {
                "tags": [
                    "Drafts"
                ],
                "summary": "Turn a draft into a scheduled post at the given time, keeping its id.",
                "description": "Schedules every account row of the draft for `schedule_date_time`. The value is read the way `/api/post_content` reads a bare time: as the wall-clock time in each account's own timezone (the workspace owner's timezone for accounts without one), so accounts in different zones publish at the same local time. An explicit offset or `Z` (for example `2026-11-03T10:00:00+05:30`) names one moment for every account instead, as `/api/post_content` does. Every resulting time must be in the future.\nThe post keeps its id and from now on appears in `/api/queue_list` and `/api/post_status` as a scheduled post. The owner's one-off post limit for that day is checked before anything changes.\n\nOffsets: With an offset or `Z` every account gets the same instant and `scheduled_for` shows it in the workspace owner's timezone. Without one, each account reads the wall clock in its own timezone.\n\nEditing afterwards: Once scheduled, the post is no longer a draft: change it with `/api/queue_post_update` or `/api/queue_reschedule`, not `/api/draft_save`, which answers 409 for it.",
                "operationId": "draft_schedule",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "draft_id": {
                                        "type": "integer",
                                        "description": "Plain numeric draft id from `/api/draft_save` or `/api/draft_list`.",
                                        "example": 48213
                                    },
                                    "schedule_date_time": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Publish time as `YYYY-MM-DD HH:MM:SS` (an ISO form such as `2026-11-03T10:00:00` is also parsed). The clock digits are applied in each account's timezone; a timezone offset or `Z` suffix is dropped, not converted.",
                                        "example": "2026-11-03 10:00:00"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "draft_id",
                                    "schedule_date_time"
                                ],
                                "example": {
                                    "draft_id": 48213,
                                    "schedule_date_time": "2026-11-03 10:00:00"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Draft scheduled.`"
                                        },
                                        "post_data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The post id, unchanged from `draft_id`."
                                                },
                                                "account_count": {
                                                    "type": "integer",
                                                    "description": "Number of social accounts the post was scheduled for."
                                                },
                                                "scheduled_for": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "description": "The wall-clock time applied, `YYYY-MM-DD HH:MM:SS`."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Draft scheduled.",
                                    "post_data": {
                                        "id": 48213,
                                        "account_count": 2,
                                        "scheduled_for": "2026-11-03 10:00:00"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (draft_id or schedule_date_time is missing.)\n\nschedule_date_time is not a valid date and time. (schedule_date_time cannot be parsed.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (draft_id does not belong to the workspace owner.)\n\nYou have reached your post limit for the selected date. ... to schedule more posts. (The owner's plan allows no more one-off posts on that day. Nothing is changed.)\n\nYou have reached your N-post limit on the 14-day free trial. Please purchase a plan to schedule more posts. (A trial workspace has used its post allowance.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (You are not the owner or an active member of that workspace.)\n\nDraft not found. (draft_id names a post with no account rows.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This post is not a draft. (The post is already scheduled, published or deleted.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Oops! You need to schedule your update for a time in the future! (The time is in the past for at least one of the draft's accounts.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/draft_delete": {
            "post": {
                "tags": [
                    "Drafts"
                ],
                "summary": "Delete a draft and every account row it holds.",
                "description": "Removes the draft for all of its social accounts. Each account row is deleted through the app, so the dashboard and the drafts board reflect it at once. The call succeeds when at least one row was removed.",
                "operationId": "draft_delete",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "draft_id": {
                                        "type": "integer",
                                        "description": "Plain numeric draft id from `/api/draft_save` or `/api/draft_list`.",
                                        "example": 48213
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "draft_id"
                                ],
                                "example": {
                                    "draft_id": 48213
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Draft deleted.`"
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Draft deleted."
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (draft_id is missing or 0.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (draft_id does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (You are not the owner or an active member of that workspace.)\n\nDraft not found. (draft_id names a post with no account rows.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This post is not a draft. (The post is scheduled, published or deleted; remove a scheduled post with /api/queue_post_delete.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The draft could not be deleted. (None of the draft's account rows could be removed.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/queue_list": {
            "post": {
                "tags": [
                    "Queue"
                ],
                "summary": "Queued items of the workspace in a date window, one per account and time.",
                "description": "Returns the posts not yet published, failed or deleted, ordered by post time ascending. `from` and `to` are dates in the workspace owner's timezone; they default to today and 30 days ahead. Narrow the list with `account_id` and `library_id`.\nThe `id` of each item is the plain integer the other queue endpoints take. `post_id` is shared by the items of one post on several accounts.\n\nTwo timezones: `from` and `to` are read in the workspace owner's timezone, but each item's `post_date` is shown in its own social account's timezone. Convert before comparing items across accounts.\n\nFailed posts are not here: The list holds items that are still to go out. Published and failed posts come from `/api/history_list`; a failed item can be retried with `/api/post_retry`.",
                "operationId": "queue_list",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7xQ2pL9k=="
                                    },
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted social account id from `/api/social_account_list`; one id, a comma-separated list or an array. Only items on these accounts are returned.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted library id from `/api/library_list`; one id, a comma-separated list or an array. Only items coming from these libraries are returned.",
                                        "example": "lB4m2Rt8Zq=="
                                    },
                                    "from": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "First day of the window, `YYYY-MM-DD` in the owner's timezone. Defaults to today.",
                                        "default": "today",
                                        "example": "2026-10-22"
                                    },
                                    "to": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Last day of the window, `YYYY-MM-DD` in the owner's timezone, not before `from`. Defaults to 30 days after today, or to `from` when that lies further out.",
                                        "default": "today + 30 days",
                                        "example": "2026-11-21"
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Page number, starting at 1.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "per_page": {
                                        "type": "integer",
                                        "description": "Items per page, 1 to 50.",
                                        "default": "20",
                                        "example": 20
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "total": {
                                            "type": "integer",
                                            "description": "Number of items in the window after the filters."
                                        },
                                        "page": {
                                            "type": "integer",
                                            "description": "Page returned."
                                        },
                                        "per_page": {
                                            "type": "integer",
                                            "description": "Page size used."
                                        },
                                        "from": {
                                            "type": "string",
                                            "format": "date",
                                            "description": "First day of the window actually used."
                                        },
                                        "to": {
                                            "type": "string",
                                            "format": "date",
                                            "description": "Last day of the window actually used."
                                        },
                                        "items": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Queue item id (plain integer). Pass it to the other queue endpoints."
                                                    },
                                                    "post_id": {
                                                        "type": "integer",
                                                        "description": "Id of the post content this item publishes; shared by the items of one post on other accounts."
                                                    },
                                                    "account": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "description": "Encrypted social account id."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Account name as shown in RecurPost."
                                                            },
                                                            "network": {
                                                                "type": "string",
                                                                "description": "`facebook`, `twitter`, `linkedin`, `instagram`, `pinterest`, `google_my_business`, `tiktok`, `youtube`, `threads` or `bluesky`."
                                                            }
                                                        }
                                                    },
                                                    "library": {
                                                        "type": "object",
                                                        "description": "`{id, name}` of the library the item was taken from (encrypted id), or `null` for a one-off post."
                                                    },
                                                    "message": {
                                                        "type": "string",
                                                        "description": "Post text."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Link preview title, empty when there is none."
                                                    },
                                                    "description": {
                                                        "type": "string",
                                                        "description": "Link preview description."
                                                    },
                                                    "url": {
                                                        "type": "string",
                                                        "description": "Link of the post."
                                                    },
                                                    "image_url": {
                                                        "type": "string",
                                                        "description": "First image URL."
                                                    },
                                                    "video_url": {
                                                        "type": "string",
                                                        "description": "Video URL, empty when there is none."
                                                    },
                                                    "post_date": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "Scheduled time, `YYYY-MM-DD HH:MM:SS` in the social account's timezone."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "`scheduled`, or `pending` for an item still being prepared (for example a video being processed)."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "total": 2,
                                    "page": 1,
                                    "per_page": 20,
                                    "from": "2026-10-22",
                                    "to": "2026-11-21",
                                    "items": [
                                        {
                                            "id": 48213,
                                            "post_id": 9051,
                                            "account": {
                                                "id": "nX2k9Qp7Lw==",
                                                "name": "Acme Page",
                                                "network": "facebook"
                                            },
                                            "library": {
                                                "id": "lB4m2Rt8Zq==",
                                                "name": "Evergreen"
                                            },
                                            "message": "Three ways to plan a month of posts in an hour",
                                            "title": "Plan a month of posts",
                                            "description": "A short guide to batching social content.",
                                            "url": "https://example.com/plan",
                                            "image_url": "https://cdn.example.com/u/1/images/plan.jpg",
                                            "video_url": "",
                                            "post_date": "2026-10-23 09:30:00",
                                            "status": "scheduled"
                                        },
                                        {
                                            "id": 48214,
                                            "post_id": 9051,
                                            "account": {
                                                "id": "tW8c3Vb1Ym==",
                                                "name": "@acme",
                                                "network": "twitter"
                                            },
                                            "library": null,
                                            "message": "Three ways to plan a month of posts in an hour",
                                            "title": "",
                                            "description": "",
                                            "url": "",
                                            "image_url": "",
                                            "video_url": "",
                                            "post_date": "2026-10-23 04:00:00",
                                            "status": "pending"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (account_id or library_id was sent but holds an id that does not decrypt.)\n\nfrom and to must be dates as YYYY-MM-DD, with from not after to. (A date is not a real calendar date in that format, or from is later than to.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/queue_post": {
            "post": {
                "tags": [
                    "Queue"
                ],
                "summary": "One queued item by its id.",
                "description": "Returns one item of the queue in the same shape as `/api/queue_list`. The id must belong to the workspace owner and still be queued; a published or removed item answers 404.",
                "operationId": "queue_post",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Queue item id (plain integer) from `/api/queue_list`.",
                                        "example": 48213
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. When given, the item's account must sit in that workspace.",
                                        "example": "wS7xQ2pL9k=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 48213
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "item": {
                                            "type": "object",
                                            "description": "The queue item, same fields as one entry of `items[]` in `/api/queue_list`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "item": {
                                        "id": 48213,
                                        "post_id": 9051,
                                        "account": {
                                            "id": "nX2k9Qp7Lw==",
                                            "name": "Acme Page",
                                            "network": "facebook"
                                        },
                                        "library": {
                                            "id": "lB4m2Rt8Zq==",
                                            "name": "Evergreen"
                                        },
                                        "message": "Three ways to plan a month of posts in an hour",
                                        "title": "Plan a month of posts",
                                        "description": "A short guide to batching social content.",
                                        "url": "https://example.com/plan",
                                        "image_url": "https://cdn.example.com/u/1/images/plan.jpg",
                                        "video_url": "",
                                        "post_date": "2026-10-23 09:30:00",
                                        "status": "scheduled"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or not a positive integer.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The id belongs to another user.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Queued post not found. It may have been published or removed. (No queued item with that id exists for the owner (or, with workspace_id, inside that workspace).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/queue_post_update": {
            "post": {
                "tags": [
                    "Queue"
                ],
                "summary": "Move a queued item to a new time, replace its content, or both.",
                "description": "Send `schedule_date_time` to move the item, `message` plus any of the content fields of `/api/post_content` to rewrite it, or both together.\nTime only: the item must be in status `scheduled`. The new time is checked against the owner's daily post limit and written in place; sending the item's current time changes nothing. The answer is `Post rescheduled`.\nWith content: the item is rebuilt from the fields you send, as `/api/post_content` would build a new post (media is fetched and hosted again, link previews resolved). The rewrite is copy-on-write: a new post content record is created and only this queue item is pointed at it, so the item keeps its `id` but gets a new `post_id`, while the other accounts of the original post keep the old content and `post_id`. Fields you leave out are not kept from the old content. The answer is `Post updated`.\nOnly the per-network fields of this item's network take effect; the others are accepted and ignored.\n\nCopy-on-write ids: After a content change the item keeps its queue `id` but its `post_id` changes, and only this account's copy is rewritten. Re-read `/api/queue_list` if you track posts by `post_id`.\n\nTimezones: A bare `schedule_date_time` is read in the workspace owner's timezone, not the account's. Send an explicit offset to avoid ambiguity. The new time is then shown in `/api/queue_list` in the account's timezone.\n\nContent fields: The content parameters are the ones of `/api/post_content`; see that endpoint for the full rules per network. Media is downloaded and hosted during the call, so a rewrite with a video can take a while.\n\nOne account, so no per-network text or media: A queue item is one post on one account, so send the text in `message` and the media in `image_url` / `video_url`. The per-network text and media fields of `/api/post_content` (`fb_message`, `in_image_url`, `th_media_order` and the rest) are still accepted for compatibility, but only the ones matching this item's network have any effect and they give the same result as the shared fields. The network options below (`fb_post_type`, `in_post_type`, `yt_title` and so on) do apply when they match the item's network.",
                "operationId": "queue_post_update",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Queue item id (plain integer) from `/api/queue_list`.",
                                        "example": 48213
                                    },
                                    "schedule_date_time": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "New time, in the future. Required when no `message` is sent. A value with an offset or `Z` (`2026-10-25T09:30:00+05:30`) is taken as is; a bare `YYYY-MM-DD HH:MM:SS` is read in the workspace owner's timezone.",
                                        "example": "2026-10-25 09:30:00"
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "New post text; the item is one post on one account, so this is the text that goes out. Required when any content field (`url`, `image_url`, `video_url`) is sent. Its presence switches the call to a content rewrite.",
                                        "example": "Updated: three ways to plan a month of posts"
                                    },
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link to attach. On a text post the first link in `message` is used when this is empty. For Pinterest it becomes the pin's destination.",
                                        "example": "https://example.com/plan"
                                    },
                                    "image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Public image URL or an array of up to 20. Each is downloaded and hosted by RecurPost unless it already comes from `/api/media_upload_url`.",
                                        "example": [
                                            "https://example.com/img/plan.jpg"
                                        ]
                                    },
                                    "video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public mp4 or mov URL (2 GB at most). Not available on free plans. Images and a video together make a mixed post.",
                                        "example": "https://example.com/video/plan.mp4"
                                    },
                                    "host_images_on_recurpost": {
                                        "type": "boolean",
                                        "description": "Copy images and custom thumbnails to RecurPost storage (the default). Send `false`, `0` or the form string `\"false\"` to keep your own URLs instead; they must then stay reachable until every post using them has been published.",
                                        "default": "true",
                                        "example": true
                                    },
                                    "media_order": {
                                        "type": "array",
                                        "items": [],
                                        "description": "For a mixed post: the `image_url` and `video_url` values in the order to show them. Only those URLs are allowed.",
                                        "example": [
                                            "https://example.com/video/plan.mp4",
                                            "https://example.com/img/plan.jpg"
                                        ]
                                    },
                                    "alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alt text for the images, one string or a list in `image_url` order, 1000 characters each at most. Applied on Facebook, X, LinkedIn, Pinterest, Threads and Bluesky.",
                                        "example": [
                                            "A monthly content calendar"
                                        ]
                                    },
                                    "first_comment": {
                                        "type": "string",
                                        "description": "Comment posted right after the post on Facebook, Instagram and LinkedIn. Overridden per network by `fb_first_comment`, `in_first_comment`, `ln_first_comment`.",
                                        "example": "Full guide in our bio."
                                    },
                                    "fb_post_type": {
                                        "type": "string",
                                        "description": "Facebook post type.",
                                        "enum": [
                                            "feed",
                                            "reel",
                                            "story"
                                        ],
                                        "default": "feed",
                                        "example": "feed"
                                    },
                                    "fb_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Cover image for a Facebook video or reel; ignored without `video_url`.",
                                        "example": "https://example.com/img/cover.jpg"
                                    },
                                    "fb_first_comment": {
                                        "type": "string",
                                        "description": "First comment on Facebook.",
                                        "example": "More in the comments."
                                    },
                                    "fb_mentions": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Facebook pages to mention, at most 10: page ids from `/api/mention_search`, as a list of ids or of `{page_id, name}` objects. Write each page in the text as `@<page id>`; the publisher turns it into the page's mention on Facebook pages.",
                                        "example": [
                                            {
                                                "page_id": "108296975869040",
                                                "name": "Acme"
                                            }
                                        ]
                                    },
                                    "fb_background_id": {
                                        "type": "string",
                                        "description": "Facebook text background for a post without `image_url` or `video_url`: an id from `/api/facebook_backgrounds` (letters, digits, underscore or dash, up to 64 characters). Applied on Facebook pages only.",
                                        "example": "106"
                                    },
                                    "ln_document": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public PDF, PPT, PPTX, DOC or DOCX to post as a LinkedIn document.",
                                        "example": "https://example.com/deck.pdf"
                                    },
                                    "ln_document_title": {
                                        "type": "string",
                                        "description": "Title of the LinkedIn document; defaults to the file name.",
                                        "example": "Q4 planning deck"
                                    },
                                    "ln_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Cover image for a LinkedIn video; ignored without `video_url`.",
                                        "example": "https://example.com/img/cover.jpg"
                                    },
                                    "ln_first_comment": {
                                        "type": "string",
                                        "description": "First comment on LinkedIn.",
                                        "example": "Link to the guide below."
                                    },
                                    "in_post_type": {
                                        "type": "string",
                                        "description": "Instagram post type.",
                                        "enum": [
                                            "feed",
                                            "story",
                                            "reel"
                                        ],
                                        "default": "feed",
                                        "example": "feed"
                                    },
                                    "in_reel_share_in_feed": {
                                        "type": "string",
                                        "description": "For reels: `no` keeps the reel out of the feed.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "in_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Cover image for an Instagram reel; ignored for feed and story posts.",
                                        "example": "https://example.com/img/cover.jpg"
                                    },
                                    "in_first_comment": {
                                        "type": "string",
                                        "description": "First comment on Instagram.",
                                        "example": "Save this for later."
                                    },
                                    "in_location_id": {
                                        "type": "string",
                                        "description": "Instagram location id from `/api/instagram_locations`; needs `in_location_name`.",
                                        "example": "212988663"
                                    },
                                    "in_location_name": {
                                        "type": "string",
                                        "description": "Name of the Instagram location, required with `in_location_id`.",
                                        "example": "New York, New York"
                                    },
                                    "in_location_city": {
                                        "type": "string",
                                        "description": "City of the Instagram location.",
                                        "example": "New York"
                                    },
                                    "in_location_country": {
                                        "type": "string",
                                        "description": "Country of the Instagram location.",
                                        "example": "United States"
                                    },
                                    "in_image_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Instagram user tags on images: objects with `username`, `x` and `y` (0 to 1) and `image` (1-based position in `image_url`).",
                                        "example": [
                                            {
                                                "image": 1,
                                                "username": "acme",
                                                "x": 0.5,
                                                "y": 0.4
                                            }
                                        ]
                                    },
                                    "in_reel_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Usernames to tag on an Instagram reel; needs `video_url`.",
                                        "example": [
                                            "acme"
                                        ]
                                    },
                                    "in_collaborators": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Up to 3 Instagram collaborator usernames.",
                                        "example": [
                                            "acme"
                                        ]
                                    },
                                    "in_audio_id": {
                                        "type": "string",
                                        "description": "Instagram audio to lay under a reel, from `/api/instagram_audio_search`. Needs `in_post_type` reel, a `video_url` and `in_audio_account_id`.",
                                        "example": "1234567890123456"
                                    },
                                    "in_audio_account_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the Instagram account `/api/instagram_audio_search` ran for. Required with `in_audio_id`.",
                                        "example": "aK3mZ8vQr1=="
                                    },
                                    "in_audio_type": {
                                        "type": "string",
                                        "description": "Kind of audio behind `in_audio_id`.",
                                        "enum": [
                                            "music",
                                            "original_sound"
                                        ],
                                        "default": "music",
                                        "example": "music"
                                    },
                                    "in_audio_title": {
                                        "type": "string",
                                        "description": "Title of the audio, as the search returned it; stored with the reel.",
                                        "example": "Summer Nights"
                                    },
                                    "in_audio_artist": {
                                        "type": "string",
                                        "description": "Artist of the audio, as the search returned it.",
                                        "example": "The Examples"
                                    },
                                    "in_audio_duration_ms": {
                                        "type": "integer",
                                        "description": "Length of the audio in milliseconds, as the search returned it.",
                                        "example": 30000
                                    },
                                    "in_audio_volume": {
                                        "type": "integer",
                                        "description": "Volume of the added audio, 0 to 100.",
                                        "default": "100",
                                        "example": 100
                                    },
                                    "in_video_volume": {
                                        "type": "integer",
                                        "description": "Volume of the reel's own sound, 0 to 100.",
                                        "default": "100",
                                        "example": 100
                                    },
                                    "in_trial_reel": {
                                        "type": "string",
                                        "description": "Publish the reel as a trial reel, shown to non-followers first. `manual`: you decide in Instagram when to share it with followers; `performance`: Instagram shares it when it does well. Reels only.",
                                        "enum": [
                                            "manual",
                                            "performance"
                                        ],
                                        "example": "manual"
                                    },
                                    "in_product_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Instagram product tags on images: objects with `account_id` (encrypted, the account whose catalog holds the product), `product_id` (from `/api/instagram_products`), `image` (1-based position in `image_url`), `x` and `y` (0 to 1, default 0.5), and optionally `product_name` and `product_image`.",
                                        "example": [
                                            {
                                                "image": 1,
                                                "account_id": "aK3mZ8vQr1==",
                                                "product_id": "901000111222333",
                                                "x": 0.5,
                                                "y": 0.6
                                            }
                                        ]
                                    },
                                    "in_reel_product_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Products tagged on a reel: objects with `account_id` (encrypted) and `product_id` (from `/api/instagram_products`), optionally `product_name` and `image_url`. Reels only.",
                                        "example": [
                                            {
                                                "account_id": "aK3mZ8vQr1==",
                                                "product_id": "901000111222333"
                                            }
                                        ]
                                    },
                                    "pi_title": {
                                        "type": "string",
                                        "description": "Pinterest pin title.",
                                        "example": "Plan a month of posts"
                                    },
                                    "gbp_cta": {
                                        "type": "string",
                                        "description": "Google Business call to action button.",
                                        "enum": [
                                            "Learn more",
                                            "Sign up",
                                            "Buy",
                                            "Order online",
                                            "Book",
                                            "Call now",
                                            "None",
                                            "Offer"
                                        ],
                                        "example": "Learn more"
                                    },
                                    "gbp_cta_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link behind the Google Business button.",
                                        "example": "https://example.com/plan"
                                    },
                                    "gbp_offer_title": {
                                        "type": "string",
                                        "description": "Google Business offer title (with `gbp_cta` Offer).",
                                        "example": "20% off planning"
                                    },
                                    "gbp_offer_start_date": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Offer start, `YYYY-MM-DD HH:MM:SS`.",
                                        "example": "2026-11-01 00:00:00"
                                    },
                                    "gbp_offer_end_date": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Offer end, `YYYY-MM-DD HH:MM:SS`.",
                                        "example": "2026-11-30 23:59:59"
                                    },
                                    "gbp_offer_coupon_code": {
                                        "type": "string",
                                        "description": "Offer coupon code.",
                                        "example": "PLAN20"
                                    },
                                    "gbp_offer_terms": {
                                        "type": "string",
                                        "description": "Offer terms and conditions.",
                                        "example": "One per customer."
                                    },
                                    "gbp_redeem_offer_link": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link to redeem the offer; defaults to `gbp_cta_url`.",
                                        "example": "https://example.com/redeem"
                                    },
                                    "yt_title": {
                                        "type": "string",
                                        "description": "YouTube video title.",
                                        "example": "Plan a month of posts in an hour"
                                    },
                                    "yt_category": {
                                        "type": "string",
                                        "description": "YouTube category name, for example `Education`; the owner's default category when omitted or unknown.",
                                        "example": "Education"
                                    },
                                    "yt_privacy_status": {
                                        "type": "string",
                                        "description": "YouTube privacy.",
                                        "enum": [
                                            "public",
                                            "private",
                                            "unlisted"
                                        ],
                                        "example": "public"
                                    },
                                    "yt_user_tags": {
                                        "type": "string",
                                        "description": "Comma-separated YouTube tags.",
                                        "example": "planning,social media"
                                    },
                                    "yt_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "YouTube thumbnail image.",
                                        "example": "https://example.com/img/cover.jpg"
                                    },
                                    "yt_video_made_for_kids": {
                                        "type": "string",
                                        "description": "`yes` marks the video as made for kids.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "no",
                                        "example": "no"
                                    },
                                    "tk_privacy_status": {
                                        "type": "string",
                                        "description": "Who can watch the TikTok video. Case-insensitive, spaces or underscores. Any other value is saved as `Public to Everyone`; omitted leaves it unset. `/api/tiktok_options` lists what the account allows.",
                                        "enum": [
                                            "Public to Everyone",
                                            "Mutual Follow Friends",
                                            "Self Only"
                                        ],
                                        "example": "Public to Everyone"
                                    },
                                    "tk_allow_comments": {
                                        "type": "string",
                                        "description": "`no` disables comments on TikTok.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_allow_duet": {
                                        "type": "string",
                                        "description": "`no` disables duets on TikTok.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_allow_stitches": {
                                        "type": "string",
                                        "description": "`no` disables stitches on TikTok.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_promote_own_brand": {
                                        "type": "integer",
                                        "description": "`1` marks the TikTok post as promoting your own brand.",
                                        "enum": [
                                            0,
                                            1
                                        ],
                                        "default": "0",
                                        "example": 0
                                    },
                                    "tk_promote_other_brand": {
                                        "type": "integer",
                                        "description": "`1` marks the TikTok post as branded content for a third party.",
                                        "enum": [
                                            0,
                                            1
                                        ],
                                        "default": "0",
                                        "example": 0
                                    },
                                    "twitter_thread": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Up to 25 follow-up tweets, each an object with `message` and optionally `image_url` (up to 4) or `video_url` (not both).",
                                        "example": [
                                            {
                                                "message": "Step one: pick your themes."
                                            }
                                        ]
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 48213
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Post rescheduled` after a time-only change, `Post updated` after a content change."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Post updated"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or not a positive integer.)\n\nmessage is required when changing a post's content. (url, image_url or video_url was sent without message.)\n\nSend a new schedule_date_time, new content, or both. (Neither schedule_date_time nor message was sent.)\n\nschedule_date_time must be a datetime like 2026-10-20T09:30:00+05:30. (schedule_date_time does not parse.)\n\nschedule_date_time must be in the future. (The new time is now or earlier.)\n\nimage_url takes at most 20 images. (More than 20 images. The other option checks answer 400 the same way: alt_text over 1000 characters, in_location_id without in_location_name, more than 3 in_collaborators, in_reel_tags without video_url, malformed in_image_tags, media_order holding an unknown URL, more than 25 twitter_thread items, a thread item without content or with images and a video.)\n\nin_audio_id needs in_post_type reel with a video_url, in_audio_account_id (the account instagram_audio_search ran for), in_audio_type music or original_sound, and volumes from 0 to 100. (in_audio_id is sent without those conditions.)\n\nin_trial_reel is manual or performance, on in_post_type reel only. (in_trial_reel has another value or the post is not a reel.)\n\nin_product_tags entries need account_id, product_id (from instagram_products), image as a position in image_url, and x and y between 0 and 1. (An in_product_tags entry is malformed or points past the last image.)\n\nin_reel_product_tags entries need account_id and product_id, on in_post_type reel only. (An in_reel_product_tags entry is malformed or the post is not a reel.)\n\nfb_mentions holds page ids from mention_search, as a list or as {page_id, name} items. (An fb_mentions entry is not a numeric page id.)\n\nfb_mentions takes at most 10 pages. (More than 10 pages in fb_mentions.)\n\nfb_background_id takes a background id from facebook_backgrounds, on a post without image_url or video_url. (fb_background_id is sent with media, or is not a plain id.)\n\n<prefix>_image_url / <prefix>_video_url must leave <network> at least one image or a video. (A per-network media field is sent empty.)\n\nyt_image_url is not accepted; YouTube takes yt_video_url only. (Images sent for YouTube.)\n\n<prefix>_image_url and <prefix>_video_url cannot be combined; only Instagram and Threads take images and a video together. (Images and a video for one network other than Instagram or Threads.)\n\n<prefix>_image_url takes at most <n> images for <network>. (More images than that network allows. Instagram and Threads count images and video together and answer \"_image_url and _video_url take at most  media items together for .\")\n\n<prefix>_media_order may only hold the URLs given in <prefix>_image_url and <prefix>_video_url. (A per-network order names a URL outside that network's own media.)\n\n<prefix>_alt_text entries may have at most 1000 characters. (A per-network alt text entry is longer than 1000 characters.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The id belongs to another user.)\n\nYou have reached your post limit for the selected date. ... (The owner's daily post limit is full on the new day (time-only change). The exact text comes from the app.)\n\nYou are not allowed to upload video file in your current plan. Please upgrade your RecurPost plan. (video_url on a free plan.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Queue item not found. (No item with that id exists for the owner (or inside the given workspace).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This post is no longer queued; it has been published or removed. (The item's status is published, failed or deleted.)\n\nOnly a scheduled item can be moved on its own; this one is pending. Send its content as well to save it again. (A time-only change on an item that is not in status scheduled.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Media URL is not allowed: ... Please supply a publicly reachable http or https URL. (An image, video, thumbnail or document URL is not a public http(s) URL.)\n\nInvalid url parameter supplied (url (or the Pinterest destination) is not a valid public URL.)\n\nURL is not a video (detected content type: ...). Please supply a valid video URL. (video_url does not serve a video. Related 415s: Invalid video format (only mp4 and mov), Failed to upload video, Invalid image url parameter supplied, URL is not an image, Failed to upload image, Invalid fb_thumb/in_thumb/ln_thumb/yt_thumb parameter supplied, Files are limited to 2 GB.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "(per-network validation message) (The content fails the network's rules (length, media); the body carries error_details per network.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app could not save the rewrite; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/queue_post_delete": {
            "post": {
                "tags": [
                    "Queue"
                ],
                "summary": "Remove one or several queued items.",
                "description": "Removes the given items from the queue. Every id must belong to the owner and still be queued, or nothing is removed. Other accounts of the same post keep their items. Each item is removed on its own; the answer counts the removed ones and lists the ids the app refused.",
                "operationId": "queue_post_delete",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Queue item ids (plain integers): one id, a comma-separated list or an array, at most 50.",
                                        "example": [
                                            48213,
                                            48214
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7xQ2pL9k=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": [
                                        48213,
                                        48214
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "deleted_count": {
                                            "type": "integer",
                                            "description": "Number of items removed."
                                        },
                                        "failed": {
                                            "type": "array",
                                            "items": [],
                                            "description": "Ids the app refused to remove. Only present when at least one failed."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "deleted_count": 2
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or holds no positive integer.)\n\nAt most 50 ids per call; N were sent. (More than 50 ids.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (An id belongs to another user.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Every id must be a queued item that is not yet published, failed or deleted. (At least one id is not a queued item of the owner (or of the given workspace). Nothing is removed.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/queue_reschedule": {
            "post": {
                "tags": [
                    "Queue"
                ],
                "summary": "Move queued items to another day, keeping each item's time of day.",
                "description": "Moves items to `to_date` the way dragging a day on the calendar does: every item keeps its time of day in its account's timezone, only the date changes. Pick the items either by `id` (one or several) or by `from_date`, which takes every queued item of that day, optionally narrowed by `account_ids` and `library_id`.\nItems of one post that sit on one day are moved together in one step; a step the app refuses (daily post limit, past time, slot already taken) is reported in `failed` while the others still move. When nothing could be moved the first refusal is returned as the error.\n\nPartial success is a 200: Check `failed` on every 200; a group the app refused stays on its old day while the rest moved.\n\nTimes are kept: Only the date changes. An item at 09:30 in its account's timezone is at 09:30 on `to_date`. Moving to today can hit the past-time refusal for items whose time of day has already passed.",
                "operationId": "queue_reschedule",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "to_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Target day, `YYYY-MM-DD` in the workspace owner's timezone.",
                                        "example": "2026-10-30"
                                    },
                                    "id": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Queue item ids (plain integers): one id, a comma-separated list or an array, at most 50. Required when `from_date` is not sent.",
                                        "example": [
                                            48213,
                                            48214
                                        ]
                                    },
                                    "from_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Day to move, `YYYY-MM-DD` in the owner's timezone. Required when `id` is not sent; ignored when it is.",
                                        "example": "2026-10-23"
                                    },
                                    "account_ids": {
                                        "type": "string",
                                        "description": "With `from_date`: encrypted social account ids (one, comma-separated or an array) to limit the move to those accounts.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "library_id": {
                                        "type": "string",
                                        "description": "With `from_date`: encrypted library id to limit the move to items from that library.",
                                        "example": "lB4m2Rt8Zq=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7xQ2pL9k=="
                                    }
                                },
                                "required": [
                                    "to_date"
                                ],
                                "example": {
                                    "to_date": "2026-10-30"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 when at least one item moved."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`N queue item(s) moved to YYYY-MM-DD.`"
                                        },
                                        "moved": {
                                            "type": "array",
                                            "items": [],
                                            "description": "Ids of the items that moved."
                                        },
                                        "failed": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "ids": {
                                                        "type": "array",
                                                        "items": [],
                                                        "description": "Ids of one post-and-day group the app refused."
                                                    },
                                                    "status": {
                                                        "type": "integer",
                                                        "description": "403 for the daily post limit, 409 for a slot already taken, 400 otherwise."
                                                    },
                                                    "error": {
                                                        "type": "string",
                                                        "description": "The app's reason."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "2 queue item(s) moved to 2026-10-30.",
                                    "moved": [
                                        48213,
                                        48214
                                    ],
                                    "failed": [
                                        {
                                            "ids": [
                                                48220
                                            ],
                                            "status": 409,
                                            "error": "Duplicate date and time are not allowed. Please choose a different slot."
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Send to_date (YYYY-MM-DD) with either id or from_date. (to_date is missing or not a date, or neither a valid id nor a valid from_date was sent.)\n\nAt most 50 ids per call; N were sent. (More than 50 ids.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\naccount_ids holds an invalid id. (An account id does not decrypt.)\n\nlibrary_id is invalid. (library_id does not decrypt.)\n\nYou can't move a post to a past time. Please select a future time. (Nothing moved and the first refusal was a target time already in the past.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (An id, account or library belongs to another user.)\n\nYou have reached your post limit for the selected date. ... (Nothing moved and the first refusal was the owner's daily post limit.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nNo queued post matches. (No queued item matches the ids or the day and filters.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Duplicate date and time are not allowed. Please choose a different slot. (Nothing moved and the first refusal was a slot already holding this post.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/queue_post_now": {
            "post": {
                "tags": [
                    "Queue"
                ],
                "summary": "Publish queued items of one post right away.",
                "description": "Publishes the given items immediately. All ids must belong to one post (same `post_id`) and still be queued. The networks are called inside the request, so the call lasts as long as they take; the answer names each account as `published` or `failed` with the network's error. When every account failed the answer is a 409 that still carries the per-account list.\n\nLong, synchronous request: Posting happens inside this call, one network after the other. Use a generous client timeout (a minute or more for videos) and do not retry blindly: a timed-out request may still have published.\n\nItems that stay failed: A failed account keeps its item in status `failed`; retry it with `/api/post_retry`.",
                "operationId": "queue_post_now",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Queue item ids (plain integers) of one post: one id, a comma-separated list or an array, at most 50.",
                                        "example": [
                                            48213,
                                            48214
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7xQ2pL9k=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": [
                                        48213,
                                        48214
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 when at least one account published."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "The app's message, normally `Post shared successfully`."
                                        },
                                        "post_id": {
                                            "type": "integer",
                                            "description": "Id of the post the items belong to."
                                        },
                                        "accounts": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Queue item id."
                                                    },
                                                    "account": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "description": "Encrypted social account id."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Account name."
                                                            },
                                                            "network": {
                                                                "type": "string",
                                                                "description": "Network key, as in `/api/queue_list`."
                                                            }
                                                        }
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "`published` or `failed`."
                                                    },
                                                    "error": {
                                                        "type": "string",
                                                        "description": "The network's error, only on a failed account."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Post shared successfully",
                                    "post_id": 9051,
                                    "accounts": [
                                        {
                                            "id": 48213,
                                            "account": {
                                                "id": "nX2k9Qp7Lw==",
                                                "name": "Acme Page",
                                                "network": "facebook"
                                            },
                                            "status": "published"
                                        },
                                        {
                                            "id": 48214,
                                            "account": {
                                                "id": "tW8c3Vb1Ym==",
                                                "name": "@acme",
                                                "network": "twitter"
                                            },
                                            "status": "failed",
                                            "error": "Token expired"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or holds no positive integer.)\n\nAt most 50 ids per call; N were sent. (More than 50 ids.)\n\nAll ids must belong to the same post. (The ids span more than one post_id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (An id belongs to another user.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Every id must be a queued item that is not yet published, failed or deleted. (At least one id is not a queued item of the owner (or of the given workspace).)\n\n(the first account's error) (Every account failed. The body also carries status 409 and the accounts list.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The post could not be published. (The app's publish call did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/post_retry": {
            "post": {
                "tags": [
                    "Queue"
                ],
                "summary": "Retry a failed queue item now or at a new time.",
                "description": "Takes one item in status `failed`. The id is the queue item id (plain integer) you got from `/api/queue_list` before the post went out, or from `accounts[].id` in the answer of `/api/queue_post_now`, or as `accounts[].queue_item_id` from `/api/post_status`, which lists every account row of a post with its state and failure reason. Without `schedule_date_time` the item is published right away through the same path as `/api/queue_post_now`, with the app's retry flag, and the answer has the same per-account shape. With `schedule_date_time` the failure is cleared and the item is put back in the queue for that time, after the owner's daily post limit is checked.\n\nAccount timezone: Unlike `/api/queue_post_update`, a bare `schedule_date_time` here is read in the social account's timezone. Send an offset to be explicit.\n\nRetry now is synchronous: Without a time the network is called inside the request; see the timeout note on `/api/queue_post_now`.",
                "operationId": "post_retry",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Queue item id (plain integer) of the failed post.",
                                        "example": 48190
                                    },
                                    "schedule_date_time": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Time to retry at, in the future. A value with an offset or `Z` is taken as is; a bare `YYYY-MM-DD HH:MM:SS` is read in the social account's timezone (the owner's when the account has none). Omit to retry now.",
                                        "example": "2026-10-25 10:00:00"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7xQ2pL9k=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 48190
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Post scheduled for retry.` when a time was given; otherwise the publish message, normally `Post shared successfully`."
                                        },
                                        "item": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "Queue item id (time given)."
                                                },
                                                "post_id": {
                                                    "type": "integer",
                                                    "description": "Id of the post (time given)."
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "`scheduled` (time given)."
                                                },
                                                "post_date": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "description": "The new time in the account's timezone (time given)."
                                                }
                                            }
                                        },
                                        "post_id": {
                                            "type": "integer",
                                            "description": "Id of the post (retried now)."
                                        },
                                        "accounts": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "One entry with `id`, `account`, `status` and `error`, as in `/api/queue_post_now` (retried now)."
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Post scheduled for retry.",
                                    "item": {
                                        "id": 48190,
                                        "post_id": 9032,
                                        "status": "scheduled",
                                        "post_date": "2026-10-25 10:00:00"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or zero.)\n\nschedule_date_time is not a valid date and time. (schedule_date_time does not parse.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The id belongs to another user.)\n\nYou have reached your post limit for the selected date. ... (The owner's daily post limit is full on that day. The exact text comes from the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Queue item not found. (No item with that id exists for the owner (or inside the given workspace).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Only a failed post can be retried; this one is scheduled. (The item is not in status failed; the word names its current status.)\n\n(the network's error) (Retried now and the network refused again; the body carries the accounts list.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Oops! You need to schedule your update for a time in the future! (schedule_date_time is now or earlier.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The post could not be published. (Retried now and the app's publish call did not answer.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/calendar": {
            "post": {
                "tags": [
                    "Queue"
                ],
                "summary": "The queue laid out by day, every day of the range present, empty days included.",
                "description": "Returns the queued items between `start_date` and `end_date` grouped by day in the workspace owner's timezone, as a calendar view needs them: one entry per day of the range, in order, with its count and items, days without posts included with an empty list. Without dates the current week is returned, Monday to Sunday. The range may span at most 42 days (six calendar weeks). `account_ids` and `library_ids` narrow the items.\nEach item is in the shape of `/api/queue_list`. Only queued items appear (scheduled or pending); published and failed posts are in `/api/history_list`.\n\nTwo clocks: Days are cut in the owner's timezone (`timezone` in the answer), while each item's `post_date` is shown in its account's timezone, as in `/api/queue_list`. An item can therefore sit under one date while its `post_date` reads another when the two zones differ.",
                "operationId": "calendar",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "start_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "First day, `YYYY-MM-DD` in the owner's timezone. Send both dates or neither; omitted together they default to this week's Monday and Sunday.",
                                        "example": "2026-11-02"
                                    },
                                    "end_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Last day, `YYYY-MM-DD`, on or after start_date and at most 41 days later.",
                                        "example": "2026-11-08"
                                    },
                                    "account_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted social account ids to limit the items to: one id, a comma-separated string, a JSON array string or an array.",
                                        "example": [
                                            "nX2k9Qp7Lw=="
                                        ]
                                    },
                                    "library_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted library ids to limit the items to posts from those libraries.",
                                        "example": [
                                            "pQ8rS2tU4v=="
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`"
                                        },
                                        "start_date": {
                                            "type": "string",
                                            "description": "First day of the range returned."
                                        },
                                        "end_date": {
                                            "type": "string",
                                            "description": "Last day of the range returned."
                                        },
                                        "timezone": {
                                            "type": "string",
                                            "description": "The owner's IANA timezone the days are cut in, for example `Asia/Kolkata`."
                                        },
                                        "total": {
                                            "type": "integer",
                                            "description": "Items across the whole range."
                                        },
                                        "days": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "date": {
                                                        "type": "string",
                                                        "description": "`YYYY-MM-DD`."
                                                    },
                                                    "count": {
                                                        "type": "integer",
                                                        "description": "Items on that day, 0 for an empty day."
                                                    },
                                                    "items": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "object",
                                                            "description": "The day's queue items, soonest first, each as `/api/queue_list` shows them: `id`, `post_id`, `account` (`id`, `name`, `network`), `library` (`id`, `name`, or null for a one-off post), `message`, `title`, `description`, `url`, `image_url`, `video_url`, `post_date`, `status`."
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "start_date": "2026-11-02",
                                    "end_date": "2026-11-03",
                                    "timezone": "Asia/Kolkata",
                                    "total": 1,
                                    "days": [
                                        {
                                            "date": "2026-11-02",
                                            "count": 0,
                                            "items": []
                                        },
                                        {
                                            "date": "2026-11-03",
                                            "count": 1,
                                            "items": [
                                                {
                                                    "id": 48213,
                                                    "post_id": 55120,
                                                    "account": {
                                                        "id": "nX2k9Qp7Lw==",
                                                        "name": "Acme Page",
                                                        "network": "facebook"
                                                    },
                                                    "library": {
                                                        "id": "pQ8rS2tU4v==",
                                                        "name": "Evergreen"
                                                    },
                                                    "message": "Three ways to plan a month of posts",
                                                    "title": "",
                                                    "description": "",
                                                    "url": "",
                                                    "image_url": "https://cdn.example.com/u/1/plan.jpg",
                                                    "video_url": "",
                                                    "post_date": "2026-11-03 15:30:00",
                                                    "status": "scheduled"
                                                }
                                            ]
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nstart_date and end_date must be YYYY-MM-DD with end_date on or after start_date. (Only one of the dates was sent, one is not a real date, or end_date comes first.)\n\nThe range may span at most 42 days. (end_date is more than 41 days after start_date.)\n\naccount_ids holds an invalid id. (An account id does not decrypt.)\n\nlibrary_ids holds an invalid id. (A library id does not decrypt.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (An account or library belongs to another user.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and an account sits in another workspace.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and a library sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/queue_post_add_accounts": {
            "post": {
                "tags": [
                    "Queue"
                ],
                "summary": "Add social accounts to a post already in the queue.",
                "description": "Adds one queue item per account in `account_ids` to post `post_id` (the `post_id` of `/api/queue_list` or `/api/post_status`), at the post's time. When that time is closer than 31 minutes the new items are placed 31 minutes from now, as the app does. Accounts already on the post are skipped, so the call is safe to repeat; it is refused only when every account given is already there.\n\nContent is shared: The new items publish the post's current content on their network. To give one account different text, rewrite its item afterwards with `/api/queue_post_update`, which copies the content for that item alone.",
                "operationId": "queue_post_add_accounts",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "post_id": {
                                        "type": "integer",
                                        "description": "Plain integer post id grouping the queue items of one post.",
                                        "example": 55120
                                    },
                                    "account_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted social account ids: one id, a comma-separated string, a JSON array string or an array, at most 50. All ids must decrypt or the list is treated as empty.",
                                        "example": [
                                            "lB4m2Rt8Zq==",
                                            "tW8c3Vb1Ym=="
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "post_id",
                                    "account_ids"
                                ],
                                "example": {
                                    "post_id": 55120,
                                    "account_ids": [
                                        "lB4m2Rt8Zq==",
                                        "tW8c3Vb1Ym=="
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Accounts added.`"
                                        },
                                        "post_id": {
                                            "type": "integer",
                                            "description": "The post you sent."
                                        },
                                        "added": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain integer id of the new queue item."
                                                    },
                                                    "account": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "description": "Encrypted social account id."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Account name."
                                                            },
                                                            "network": {
                                                                "type": "string",
                                                                "description": "facebook, twitter, linkedin, instagram, pinterest, google_my_business, tiktok, youtube, threads or bluesky."
                                                            }
                                                        }
                                                    },
                                                    "post_date": {
                                                        "type": "string",
                                                        "description": "When the item publishes, `YYYY-MM-DD HH:MM:SS` in the account's timezone."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Accounts added.",
                                    "post_id": 55120,
                                    "added": [
                                        {
                                            "id": 48290,
                                            "account": {
                                                "id": "lB4m2Rt8Zq==",
                                                "name": "Acme",
                                                "network": "twitter"
                                            },
                                            "post_date": "2026-11-03 15:30:00"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\naccount_ids must hold at least one id. (account_ids is missing or one of its ids does not decrypt.)\n\nAt most 50 ids per call; N were sent. (More than 50 account ids.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (An account belongs to another user.)\n\nYou have exceeded the number of One-off posts. Please upgrade your plan to be able to get more One-off posts per day. (The owner's daily one-off post limit is reached (the upgrade wording varies by plan).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\npost_id is not a post of this workspace. (No post with that id has items on an account of the workspace owner (or, with workspace_id, of that workspace).)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and an account sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Every account given is already on this post. (Nothing is left to add.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; its own message replaces this one when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/history_list": {
            "post": {
                "tags": [
                    "History"
                ],
                "summary": "Published and failed posts across every account of the workspace, newest first.",
                "description": "Returns the published and failed posts of the workspace in a date window, newest first, with the account each one went to and its status. The window defaults to the last 7 days and may span at most 90. Dates are read in the workspace owner's timezone and every `post_date` is shown in that timezone too.\nEach entry shows the text and media of the network's own copy of the post (the per-network tab when the post was customised, the original otherwise), the ready-to-open `post_link` on the network, and `fail_reason` when the post failed.\n\nOwner's timezone everywhere: Both the window and `post_date` use the workspace owner's timezone here, unlike `/api/history_data`, which uses the account's.\n\nFilters run after the fetch: `library_id` and `failed_only` are applied to the whole window before paging, so `total_posts` already reflects them.\n\nEntry id: `id` is the post content id, shared by the copies of one post on several accounts; tell them apart by `account.id`. Use `post_link` to open the post, `post_url` is an older field that is empty or a profile link on some networks.",
                "operationId": "history_list",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7xQ2pL9k=="
                                    },
                                    "start_date": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Start of the window, `YYYY-MM-DD` (read as 00:00:00) or `YYYY-MM-DD HH:MM:SS`, in the owner's timezone. Must be sent together with `end_date`.",
                                        "example": "2026-10-15"
                                    },
                                    "end_date": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "End of the window, `YYYY-MM-DD` (read as 23:59:59) or `YYYY-MM-DD HH:MM:SS`, in the owner's timezone; at most 90 days after `start_date`. Must be sent together with `start_date`.",
                                        "example": "2026-10-22"
                                    },
                                    "account_ids": {
                                        "type": "string",
                                        "description": "Encrypted social account ids from `/api/social_account_list`; one id, a comma-separated list or an array. Only posts on these accounts are returned.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted library id from `/api/library_list`. Only posts that came from this library are returned.",
                                        "example": "lB4m2Rt8Zq=="
                                    },
                                    "failed_only": {
                                        "type": "boolean",
                                        "description": "`true` returns only failed posts.",
                                        "default": "false",
                                        "example": false
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Page number, starting at 1.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "per_page": {
                                        "type": "integer",
                                        "description": "Posts per page, 1 to 200.",
                                        "default": "50",
                                        "example": 50
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "total_posts": {
                                            "type": "integer",
                                            "description": "Number of posts in the window after the filters."
                                        },
                                        "page": {
                                            "type": "integer",
                                            "description": "Page returned."
                                        },
                                        "per_page": {
                                            "type": "integer",
                                            "description": "Page size used."
                                        },
                                        "has_more": {
                                            "type": "boolean",
                                            "description": "`true` when a further page exists."
                                        },
                                        "history_data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Post content id (the `post_id` of the queue endpoints, as a string)."
                                                    },
                                                    "queue_item_id": {
                                                        "type": "integer",
                                                        "description": "Queue item id of this account's row (plain integer). Pass it to `/api/post_retry` when the post failed; `id` stays the post id shared by every account of the post."
                                                    },
                                                    "message": {
                                                        "type": "string",
                                                        "description": "Text sent to this network."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Link preview title, empty when there is no link."
                                                    },
                                                    "description": {
                                                        "type": "string",
                                                        "description": "Link preview description."
                                                    },
                                                    "url": {
                                                        "type": "string",
                                                        "description": "Link of the post."
                                                    },
                                                    "image_url": {
                                                        "type": "string",
                                                        "description": "First image, the video poster, or the link preview image; empty for a plain text post."
                                                    },
                                                    "video_url": {
                                                        "type": "string",
                                                        "description": "Video URL, empty when there is none."
                                                    },
                                                    "library": {
                                                        "type": "string",
                                                        "description": "Name of the library the post came from, `null` for a one-off post."
                                                    },
                                                    "extra_images": {
                                                        "type": "array",
                                                        "items": [],
                                                        "description": "Every image URL of the post, in order."
                                                    },
                                                    "post_url": {
                                                        "type": "string",
                                                        "description": "Older per-network link kept for compatibility; prefer `post_link`."
                                                    },
                                                    "post_link": {
                                                        "type": "string",
                                                        "description": "Permalink of the post on the network. Empty for failed posts, Facebook stories and networks posted through the mobile app."
                                                    },
                                                    "post_type": {
                                                        "type": "string",
                                                        "description": "`FEED`, `REEL` or `STORY`. Only on Facebook and Instagram posts."
                                                    },
                                                    "fail_reason": {
                                                        "type": "string",
                                                        "description": "The failure message. Only on failed posts."
                                                    },
                                                    "post_date": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When the post went out (or was due), `YYYY-MM-DD HH:MM:SS` in the owner's timezone."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "`published` or `failed`."
                                                    },
                                                    "account": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "description": "Encrypted social account id."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Account name."
                                                            },
                                                            "network": {
                                                                "type": "string",
                                                                "description": "`facebook`, `twitter`, `linkedin`, `instagram`, `pinterest`, `google_my_business`, `tiktok`, `youtube`, `threads` or `bluesky`."
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "total_posts": 2,
                                    "page": 1,
                                    "per_page": 50,
                                    "has_more": false,
                                    "history_data": [
                                        {
                                            "id": "9051",
                                            "queue_item_id": 4120,
                                            "message": "Three ways to plan a month of posts in an hour",
                                            "title": "Plan a month of posts",
                                            "description": "A short guide to batching social content.",
                                            "url": "https://example.com/plan",
                                            "image_url": "https://cdn.example.com/u/1/images/plan.jpg",
                                            "video_url": "",
                                            "library": "Evergreen",
                                            "extra_images": [
                                                "https://cdn.example.com/u/1/images/plan.jpg"
                                            ],
                                            "post_url": "https://www.facebook.com/1029384756_7788990011",
                                            "post_link": "https://www.facebook.com/1029384756_7788990011",
                                            "post_type": "FEED",
                                            "post_date": "2026-10-21 09:30:00",
                                            "status": "published",
                                            "account": {
                                                "id": "nX2k9Qp7Lw==",
                                                "name": "Acme Page",
                                                "network": "facebook"
                                            }
                                        },
                                        {
                                            "id": "9032",
                                            "queue_item_id": 4121,
                                            "message": "Our October planning checklist is live",
                                            "title": "",
                                            "description": "",
                                            "url": "",
                                            "image_url": "",
                                            "video_url": "",
                                            "library": null,
                                            "extra_images": [],
                                            "post_url": "https://www.twitter.com/acme/status/",
                                            "post_link": "",
                                            "fail_reason": "Token expired. Please reconnect your account.",
                                            "post_date": "2026-10-20 15:00:00",
                                            "status": "failed",
                                            "account": {
                                                "id": "tW8c3Vb1Ym==",
                                                "name": "@acme",
                                                "network": "twitter"
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "start_date and end_date must be provided together. (Only one of the two dates was sent.)\n\nDates must be YYYY-MM-DD or YYYY-MM-DD HH:MM:SS in your timezone. (A date does not match either format.)\n\nend_date must be after start_date. (end_date is earlier than start_date.)\n\nThe window may span at most 90 days. (More than 90 days between the two dates.)\n\naccount_ids holds an invalid id. (An account id does not decrypt.)\n\nlibrary_id is invalid. (library_id does not decrypt.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (An account or library belongs to another user, or is not in the given workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/history_data": {
            "post": {
                "tags": [
                    "History"
                ],
                "summary": "Posting history of one social account, built for polling.",
                "description": "Returns the published and failed posts of one social account. Without dates it behaves as a feed: the first call returns the last 30 minutes, later calls return everything since the last call that returned posts (at most one hour back). With `start_date` and `end_date` it returns up to 100 posts of that window, newest first, plus `total_posts` with the full count.\nDates and `post_date` are in the social account's timezone (UTC when the account has none). Each entry shows the text and media of the network's own copy of the post, the permalink on the network, the post type on Facebook and Instagram, and `fail_reason` on failed posts.\n\nPolling window: Without dates the start of the window is the time of your last call for this account that returned posts, capped at one hour ago; the first call covers the last 30 minutes. Posts older than an hour are only reachable with explicit dates.\n\n100 posts per call: With dates the answer holds at most 100 posts, newest first, while `total_posts` counts them all. Split a larger window into smaller ranges, or use `/api/history_list`, which pages.\n\nAccount timezone: Dates are read and shown in the social account's timezone, not the owner's. Read the account's zone from `/api/social_account_list`.\n\nLegacy endpoint: with body or Basic credentials errors arrive as HTTP 200 with the real status in the body field `status`. With a Bearer token it returns real HTTP status codes.",
                "operationId": "history_data",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted social account id from `/api/social_account_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "start_date": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Start of the window, `YYYY-MM-DD HH:MM:SS` in the account's timezone (the time part is mandatory). Must be sent together with `end_date`.",
                                        "example": "2026-10-01 00:00:00"
                                    },
                                    "end_date": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "End of the window, `YYYY-MM-DD HH:MM:SS` in the account's timezone. Must be sent together with `start_date`.",
                                        "example": "2026-10-22 23:59:59"
                                    },
                                    "is_get_video_updates": {
                                        "type": "boolean",
                                        "description": "`false` leaves video posts out.",
                                        "default": "true",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7xQ2pL9k=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": "nX2k9Qp7Lw=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "history_data": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Post content id."
                                                    },
                                                    "queue_item_id": {
                                                        "type": "integer",
                                                        "description": "Queue item id of this account's row (plain integer). Pass it to `/api/post_retry` when the post failed; `id` stays the post id shared by every account of the post."
                                                    },
                                                    "message": {
                                                        "type": "string",
                                                        "description": "Text sent to this network."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Link preview title, empty when there is no link."
                                                    },
                                                    "description": {
                                                        "type": "string",
                                                        "description": "Link preview description."
                                                    },
                                                    "url": {
                                                        "type": "string",
                                                        "description": "Link of the post."
                                                    },
                                                    "image_url": {
                                                        "type": "string",
                                                        "description": "First image, the video poster, or the link preview image; empty for a plain text post."
                                                    },
                                                    "video_url": {
                                                        "type": "string",
                                                        "description": "Video URL, empty when there is none."
                                                    },
                                                    "library": {
                                                        "type": "string",
                                                        "description": "Name of the library the post came from, `null` for a one-off post."
                                                    },
                                                    "extra_images": {
                                                        "type": "array",
                                                        "items": [],
                                                        "description": "Every image URL of the post, in order."
                                                    },
                                                    "post_url": {
                                                        "type": "string",
                                                        "description": "Older per-network link kept for compatibility; prefer `post_link`."
                                                    },
                                                    "post_link": {
                                                        "type": "string",
                                                        "description": "Permalink of the post on the network. Empty for failed posts, Facebook stories and networks posted through the mobile app."
                                                    },
                                                    "post_type": {
                                                        "type": "string",
                                                        "description": "`FEED`, `REEL` or `STORY`. Only on Facebook and Instagram posts."
                                                    },
                                                    "fail_reason": {
                                                        "type": "string",
                                                        "description": "The failure message. Only on failed posts."
                                                    },
                                                    "post_date": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When the post went out (or was due), `YYYY-MM-DD HH:MM:SS` in the account's timezone."
                                                    }
                                                }
                                            }
                                        },
                                        "total_posts": {
                                            "type": "integer",
                                            "description": "Total count of posts in the window, also beyond the 100 returned. Only present when start_date and end_date were sent."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "history_data": [
                                        {
                                            "id": "9051",
                                            "queue_item_id": 4120,
                                            "message": "Three ways to plan a month of posts in an hour",
                                            "title": "Plan a month of posts",
                                            "description": "A short guide to batching social content.",
                                            "url": "https://example.com/plan",
                                            "image_url": "https://cdn.example.com/u/1/images/plan.jpg",
                                            "video_url": "",
                                            "library": "Evergreen",
                                            "extra_images": [
                                                "https://cdn.example.com/u/1/images/plan.jpg"
                                            ],
                                            "post_url": "https://www.facebook.com/1029384756_7788990011",
                                            "post_link": "https://www.facebook.com/1029384756_7788990011",
                                            "post_type": "FEED",
                                            "post_date": "2026-10-21 09:30:00"
                                        }
                                    ],
                                    "total_posts": 1
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or does not decrypt to one account id.)\n\nstart_date and end_date must be provided together. (Only one of the two dates was sent.)\n\nInvalid start_date. Expected format: YYYY-MM-DD HH:MM:SS (e.g. 2026-01-01 00:00:00). (start_date does not match the format exactly (a bare date is refused).)\n\nInvalid end_date. Expected format: YYYY-MM-DD HH:MM:SS (e.g. 2026-01-31 23:59:59). (end_date does not match the format exactly.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "This account is not part of a RecurPost team. (The calling user has no team seat (an account state that normally does not occur).)\n\nSorry, there was an issue. Please try again later or contact support. (The account belongs to another user, or is not in the given workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/post_unpublish": {
            "post": {
                "tags": [
                    "History"
                ],
                "summary": "Delete a published item from its social network.",
                "description": "Deletes one published item (`queue_item_id`, the `queue_item_id` of `/api/history_list` and `/api/post_status`) from the network it went out on. Only networks with a delete call are supported: Facebook pages and groups, X, LinkedIn profiles and companies, Pinterest, Google Business, YouTube and Bluesky. Facebook profiles, Instagram, TikTok and Threads answer 409; remove those posts on the network itself.\nThe item stays in the history with the deletion recorded. The call needs `confirm=true`.\n\nNot reversible: The post is gone from the network together with its likes, comments and shares. RecurPost keeps the history row and marks it deleted; the post's statistics stop updating.",
                "operationId": "post_unpublish",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "queue_item_id": {
                                        "type": "integer",
                                        "description": "Plain integer id of the published item (one account at one time), from `/api/history_list` or `/api/post_status`.",
                                        "example": 9051
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be `true`; without it the call answers 400 and deletes nothing.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "queue_item_id",
                                    "confirm"
                                ],
                                "example": {
                                    "queue_item_id": 9051,
                                    "confirm": true
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Post removed from <account name>.`"
                                        },
                                        "queue_item_id": {
                                            "type": "integer",
                                            "description": "The item you sent."
                                        },
                                        "network": {
                                            "type": "string",
                                            "description": "facebook, twitter, linkedin, pinterest, google_my_business, youtube or bluesky."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Post removed from Acme Page.",
                                    "queue_item_id": 9051,
                                    "network": "facebook"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nSend confirm=true to delete the post from <account name>. (confirm is missing or not true.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nqueue_item_id is not an item of this workspace. (No item with that id belongs to the workspace owner, or (with workspace_id) to an account of that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Only a published item can be removed from its network; this one is scheduled. (The item is not published; the last word is its status (scheduled, pending, failed, deleted).)\n\nInstagram offers no call to delete a post; remove it on the network itself. (The item is on a network without a delete call; the first word names it (Facebook for a profile, Instagram, Tiktok, Threads).)\n\n(the network's refusal) (The network did not delete the post; the body carries `reconnect_required`, true when the account's token needs renewing. Without a reason from the network the text is The network refused the deletion.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/history_to_library": {
            "post": {
                "tags": [
                    "History"
                ],
                "summary": "Copy a published post into one or more libraries as evergreen content.",
                "description": "Copies post `post_id` (the `id` of a `/api/history_list` row, shared by every account the post went out on) into each library in `library_ids`, text and media included. Each copy is a new library post with its own id and counts toward the plan's library post limit.\n\nNo id cap on this call: Unlike most list parameters, `library_ids` has no 50-id limit here; every library named gets a copy and each copy counts against the plan.",
                "operationId": "history_to_library",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "post_id": {
                                        "type": "integer",
                                        "description": "Plain integer post id from `/api/history_list` (`history_data[].id`).",
                                        "example": 55120
                                    },
                                    "library_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted library ids: one id, a comma-separated string, a JSON array string or an array. All ids must decrypt or the list is treated as empty.",
                                        "example": [
                                            "nX2k9Qp7Lw==",
                                            "bT4r8Vz1Kc=="
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "post_id",
                                    "library_ids"
                                ],
                                "example": {
                                    "post_id": 55120,
                                    "library_ids": [
                                        "nX2k9Qp7Lw==",
                                        "bT4r8Vz1Kc=="
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Post copied to N library.` or `Post copied to N libraries.`"
                                        },
                                        "post_id": {
                                            "type": "integer",
                                            "description": "The post you sent."
                                        },
                                        "library_ids": {
                                            "type": "array",
                                            "items": [],
                                            "description": "Encrypted ids of the libraries the post was copied into."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Post copied to 2 libraries.",
                                    "post_id": 55120,
                                    "library_ids": [
                                        "nX2k9Qp7Lw==",
                                        "bT4r8Vz1Kc=="
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nlibrary_ids must hold at least one id. (library_ids is missing or one of its ids does not decrypt.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (A library does not belong to the workspace owner.)\n\nYou have maximum allowed number of posts in your library. Please upgrade your plan or delete few posts to add new ones. (The copies would pass the owner's library post limit (the upgrade wording varies by plan).)\n\nSorry, we could not copy this post to the library. Please try again later or contact support. (The app could not make the copy (it answers 401 internally; the API sends 403, never a credential failure).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\npost_id is not a post of this workspace. (No post with that id went out on an account of the workspace owner (or, with workspace_id, of that workspace).)\n\nThis library is not part of the selected workspace. (workspace_id was sent and a library sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_list": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Get every content library in a workspace with its id and name.",
                "description": "Returns all content libraries of the workspace, active and paused alike, as id and name pairs. The `cd_id` is the library id every other library endpoint and `/api/add_content_in_library` take.\nCall `/api/library_details` for the state, counts and seasonal window of one library.\n\nField names: This endpoint keeps its original `cd_id` / `cd_name` keys. The newer library endpoints return the same library as `id` and `name`.\n\nLegacy endpoint: with body or Basic credentials errors arrive as HTTP 200 with the real status in the body field `status`. With a Bearer token it returns real HTTP status codes.",
                "operationId": "library_list",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "library_list": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "cd_id": {
                                                        "type": "string",
                                                        "description": "Encrypted library id. Use it as `library_id` or `id` on the other library endpoints."
                                                    },
                                                    "cd_name": {
                                                        "type": "string",
                                                        "description": "Library name."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "library_list": [
                                        {
                                            "cd_id": "nX2k9Qp7Lw==",
                                            "cd_name": "Evergreen"
                                        },
                                        {
                                            "cd_id": "bT4r8Vz1Kc==",
                                            "cd_name": "Product tips"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Looks like you haven't created a content library yet. It's a good time to create one. (The workspace has no library. There is no empty-list answer on this endpoint.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_details": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Read one library: name, colour, state, one-time-use flag, seasonal window and post counts.",
                "description": "Returns one library with its state (`active` or `paused`), whether it is one-time-use, its seasonal window and the number of posts, drafts and variations it holds.",
                "operationId": "library_details",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted library id from `/api/library_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": "nX2k9Qp7Lw=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "library": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted library id."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Library name."
                                                },
                                                "color": {
                                                    "type": "string",
                                                    "description": "Hex colour shown in the calendar, e.g. `#e0e0e0`."
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "`active` or `paused`. A paused library stops filling its schedules."
                                                },
                                                "one_time_use": {
                                                    "type": "boolean",
                                                    "description": "True when each post leaves the library once it has published."
                                                },
                                                "seasonal": {
                                                    "type": "object",
                                                    "description": "`null` when the library publishes all year, otherwise the window it is active in.",
                                                    "properties": {
                                                        "from": {
                                                            "type": "string",
                                                            "description": "First day of the season as `MM/DD`."
                                                        },
                                                        "to": {
                                                            "type": "string",
                                                            "description": "Last day of the season as `MM/DD`."
                                                        }
                                                    }
                                                },
                                                "counts": {
                                                    "type": "object",
                                                    "properties": {
                                                        "posts": {
                                                            "type": "integer",
                                                            "description": "Active posts in the library."
                                                        },
                                                        "drafts": {
                                                            "type": "integer",
                                                            "description": "Draft posts in the library."
                                                        },
                                                        "variations": {
                                                            "type": "integer",
                                                            "description": "Message variations across all posts of the library."
                                                        },
                                                        "unpublished_posts": {
                                                            "type": "integer",
                                                            "description": "Active posts that have not yet gone out in the current rotation."
                                                        }
                                                    }
                                                },
                                                "created_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "description": "When the library was created, `YYYY-MM-DD HH:MM:SS` UTC. Blank when unknown."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "library": {
                                        "id": "nX2k9Qp7Lw==",
                                        "name": "Evergreen",
                                        "color": "#e0e0e0",
                                        "status": "active",
                                        "one_time_use": false,
                                        "seasonal": null,
                                        "counts": {
                                            "posts": 5,
                                            "drafts": 1,
                                            "variations": 2,
                                            "unpublished_posts": 3
                                        },
                                        "created_at": "2026-09-01 09:00:00"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or does not decrypt to a library id.)\n\nLibrary not found. (The app returned no row for the library.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "This library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\nWorkspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_create": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Create a content library in the workspace.",
                "description": "Creates a library with a name, an optional calendar colour and the one-time-use flag. The new library is active and has no schedule yet; attach one under Schedules. Set a seasonal window afterwards with `/api/library_update`.",
                "operationId": "library_create",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "description": "Library name. Leading and trailing spaces are trimmed; a blank name is a 400.",
                                        "example": "Product tips"
                                    },
                                    "color": {
                                        "type": "string",
                                        "description": "Hex colour as `#rrggbb`, shown in the calendar. Letters may be upper or lower case.",
                                        "default": "#e0e0e0",
                                        "example": "#1e90ff"
                                    },
                                    "one_time_use": {
                                        "type": "boolean",
                                        "description": "Make it a one-time-use library: each post leaves the library once it has published. Accepts `true`/`false`, `1`/`0` or the words `yes`/`no`, as `/api/library_update` does.",
                                        "default": "0",
                                        "example": false
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "name"
                                ],
                                "example": {
                                    "name": "Product tips"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Library created successfully`."
                                        },
                                        "library": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted id of the new library."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "The trimmed name as saved."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Library created successfully",
                                    "library": {
                                        "id": "bT4r8Vz1Kc==",
                                        "name": "Product tips"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (name is missing or blank.)\n\ncolor must be a hex value like #e0e0e0. (color is not a six-digit hex colour with a leading #.)\n\nYou have no permission to create library... (You are not a member of the workspace the library would be created in.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not return the new library id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_update": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Rename or recolour a library, switch one-time-use, or set or clear its seasonal window.",
                "description": "Updates one library. Every field is optional; a field left out keeps its current value. Send `seasonal_from` and `seasonal_to` together as `MM/DD` to make the library publish only inside that window each year, or send both blank to clear the window. The response is the full library as `/api/library_details` returns it.\n\nSeason days are checked against the current year: `02/29` is only accepted in a leap year. Days must be zero-padded: `2/1` is refused, `02/01` is accepted.",
                "operationId": "library_update",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted library id.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "New name. Blank or missing keeps the current name.",
                                        "example": "Evergreen 2026"
                                    },
                                    "color": {
                                        "type": "string",
                                        "description": "New hex colour as `#rrggbb`; stored lower-cased. Blank or missing keeps the current colour.",
                                        "example": "#abcdef"
                                    },
                                    "one_time_use": {
                                        "type": "boolean",
                                        "description": "`true`/`false`, `1`/`0`, `yes`/`no`. Switching a library to one-time-use is refused while any of its posts has message variations.",
                                        "example": false
                                    },
                                    "seasonal_from": {
                                        "type": "string",
                                        "description": "First day of the season as `MM/DD` (zero-padded, e.g. `12/01`). Required when seasonal_to is sent with a value. Send both fields blank to clear the season.",
                                        "example": "12/01"
                                    },
                                    "seasonal_to": {
                                        "type": "string",
                                        "description": "Last day of the season as `MM/DD`. Required when seasonal_from is sent with a value.",
                                        "example": "12/31"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": "nX2k9Qp7Lw=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Library updated.`"
                                        },
                                        "library": {
                                            "type": "object",
                                            "description": "The updated library, same fields as `/api/library_details`: `id`, `name`, `color`, `status`, `one_time_use`, `seasonal`, `counts`, `created_at`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Library updated.",
                                    "library": {
                                        "id": "nX2k9Qp7Lw==",
                                        "name": "Evergreen 2026",
                                        "color": "#abcdef",
                                        "status": "active",
                                        "one_time_use": false,
                                        "seasonal": {
                                            "from": "12/01",
                                            "to": "12/31"
                                        },
                                        "counts": {
                                            "posts": 5,
                                            "drafts": 1,
                                            "variations": 2,
                                            "unpublished_posts": 3
                                        },
                                        "created_at": "2026-09-01 09:00:00"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or does not decrypt to a library id.)\n\ncolor must be a hex value like #e0e0e0. (color is sent and is not a six-digit hex colour with a leading #.)\n\nseasonal_from and seasonal_to must both be MM/DD, or both blank to clear the season. (One of the two season fields is blank or either is not a valid MM/DD day.)\n\nYou have no permission to update library... (You are not a member of the library's workspace.)\n\nThe library could not be updated. (The app refused the change without a message.)\n\nLibrary not found. (The library row could not be read before or after the update.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "This library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\nWorkspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "There are posts with message variations in this library. Please remove those posts or their variations to convert it to one-time-use library. (one_time_use is switched on while a post in the library has variations.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_pause": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Pause a library so it stops filling its schedules, or resume it.",
                "description": "Sets the library to `paused` or back to `active`. A paused library adds no new posts to the queue. Posts from the library that are already in the queue stay scheduled; remove them under Queue if they should not go out.\n\nIdempotent: Pausing a paused library or resuming an active one answers 200 and changes nothing.",
                "operationId": "library_pause",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted library id.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "`pause` or `resume`, case-insensitive.",
                                        "enum": [
                                            "pause",
                                            "resume"
                                        ],
                                        "example": "pause"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "id",
                                    "action"
                                ],
                                "example": {
                                    "id": "nX2k9Qp7Lw==",
                                    "action": "pause"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Library paused` or `Library resumed`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Library paused"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Send the library id and action as pause or resume. (id is missing or invalid, or action is not pause or resume.)\n\nYou have no permission to pause library... (You are not a member of the library's workspace (the resume wording is `You have no permission to resume library...`).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "This library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\nWorkspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_content_list": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Page through the active posts of one library.",
                "description": "Returns the active posts of a library, 20 per page by default, in the library's rotation order: the post due to publish next comes first. Draft posts are not included; see Drafts. An empty library answers 200 with an empty `content` list.\nEach item is the post's original version. The per-network versions of a post come from `/api/library_content`.\n\nOrder is rotation order, not creation order: Posts come back in the order the library will publish them, so the first page shows what goes out next. Sort on `created_at` yourself if you need newest first.",
                "operationId": "library_content_list",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted library id.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Page number, from 1.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "per_page": {
                                        "type": "integer",
                                        "description": "Posts per page, 1 to 50. Larger values are capped at 50.",
                                        "default": "20",
                                        "example": 20
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": "nX2k9Qp7Lw=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "total": {
                                            "type": "integer",
                                            "description": "Active posts in the library across all pages."
                                        },
                                        "page": {
                                            "type": "integer",
                                            "description": "The page returned."
                                        },
                                        "per_page": {
                                            "type": "integer",
                                            "description": "The page size applied, after the cap of 50."
                                        },
                                        "content": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted post id. Use it as `id` on `/api/library_content`, `/api/library_content_update` and `/api/library_content_delete`, and as `content_id` on the variation endpoints."
                                                    },
                                                    "message": {
                                                        "type": "string",
                                                        "description": "Post text of the original version."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Link title, blank when the post has no link."
                                                    },
                                                    "description": {
                                                        "type": "string",
                                                        "description": "Link description, blank when none."
                                                    },
                                                    "url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Link URL attached to the post, blank when none."
                                                    },
                                                    "image_url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Preview image: the first attached image, otherwise the link preview image, otherwise the video thumbnail. Blank when the post has no visual."
                                                    },
                                                    "images": {
                                                        "type": "array",
                                                        "items": [],
                                                        "description": "All image URLs attached to the original version, in order."
                                                    },
                                                    "video_url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Video URL, blank when the post has no video."
                                                    },
                                                    "live_date": {
                                                        "type": "string",
                                                        "format": "date",
                                                        "description": "First day the post may publish, `YYYY-MM-DD`; blank when not limited."
                                                    },
                                                    "expire_date": {
                                                        "type": "string",
                                                        "format": "date",
                                                        "description": "Last day the post may publish, `YYYY-MM-DD`; blank when not limited."
                                                    },
                                                    "variations": {
                                                        "type": "integer",
                                                        "description": "Number of message variations the post has beyond its original text."
                                                    },
                                                    "created_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When the post was added, `YYYY-MM-DD HH:MM:SS` UTC."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "total": 7,
                                    "page": 1,
                                    "per_page": 20,
                                    "content": [
                                        {
                                            "id": "pQ8sL3vY2a==",
                                            "message": "Five ways to repurpose your best blog post",
                                            "title": "Repurposing guide",
                                            "description": "Turn one article into a week of social posts.",
                                            "url": "https://example.com/repurposing-guide",
                                            "image_url": "https://cdn.example.com/media/guide.jpg",
                                            "images": [
                                                "https://cdn.example.com/media/guide.jpg"
                                            ],
                                            "video_url": "",
                                            "live_date": "",
                                            "expire_date": "2026-12-31",
                                            "variations": 2,
                                            "created_at": "2026-10-01 10:00:00"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or does not decrypt to a library id.)\n\nSorry, something went wrong. Please try again later. (You are not a member of the library's workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "This library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\nWorkspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_content": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Read one library post with its version for every network.",
                "description": "Returns one post of a library: the original version with the same fields as a `/api/library_content_list` item, plus `library_id` and a `networks` object holding the text, link and media the post uses on each network. A network entry whose `customized` is `false` is a copy of the original.\n\ncreated_at on this endpoint: The detail row the app returns does not carry the creation time, so `created_at` is blank here. Read it from `/api/library_content_list`.",
                "operationId": "library_content",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted post id from `/api/library_content_list` or `/api/library_content_search`.",
                                        "example": "pQ8sL3vY2a=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": "pQ8sL3vY2a=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "content": {
                                            "type": "object",
                                            "description": "The post. Carries the `/api/library_content_list` item fields (`id`, `message`, `title`, `description`, `url`, `image_url`, `images`, `video_url`, `live_date`, `expire_date`, `variations`, `created_at`) plus the two below.",
                                            "properties": {
                                                "library_id": {
                                                    "type": "string",
                                                    "description": "Encrypted id of the library the post sits in."
                                                },
                                                "networks": {
                                                    "type": "object",
                                                    "description": "One entry per network version the app keeps, keyed by network: `facebook`, `twitter`, `linkedin`, `instagram`, `google_my_business`, `pinterest`, `tiktok`, `youtube`, `threads`, `bluesky`. Empty when the post has no per-network versions.",
                                                    "properties": {
                                                        "{network}": {
                                                            "type": "object",
                                                            "properties": {
                                                                "customized": {
                                                                    "type": "boolean",
                                                                    "description": "True when this network's version differs from the original (flagged in the app, or its message or link differs)."
                                                                },
                                                                "message": {
                                                                    "type": "string",
                                                                    "description": "Text used on this network."
                                                                },
                                                                "title": {
                                                                    "type": "string",
                                                                    "description": "Link title on this network."
                                                                },
                                                                "description": {
                                                                    "type": "string",
                                                                    "description": "Link description on this network."
                                                                },
                                                                "url": {
                                                                    "type": "string",
                                                                    "format": "uri",
                                                                    "description": "Link URL on this network."
                                                                },
                                                                "images": {
                                                                    "type": "array",
                                                                    "items": [],
                                                                    "description": "Image URLs used on this network."
                                                                },
                                                                "video_url": {
                                                                    "type": "string",
                                                                    "format": "uri",
                                                                    "description": "Video URL used on this network, blank when none."
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "content": {
                                        "id": "pQ8sL3vY2a==",
                                        "message": "Five ways to repurpose your best blog post",
                                        "title": "Repurposing guide",
                                        "description": "Turn one article into a week of social posts.",
                                        "url": "https://example.com/repurposing-guide",
                                        "image_url": "https://cdn.example.com/media/guide.jpg",
                                        "images": [
                                            "https://cdn.example.com/media/guide.jpg"
                                        ],
                                        "video_url": "",
                                        "live_date": "",
                                        "expire_date": "2026-12-31",
                                        "variations": 2,
                                        "created_at": "",
                                        "library_id": "nX2k9Qp7Lw==",
                                        "networks": {
                                            "twitter": {
                                                "customized": true,
                                                "message": "5 ways to repurpose your best post (thread)",
                                                "title": "Repurposing guide",
                                                "description": "Turn one article into a week of social posts.",
                                                "url": "https://example.com/repurposing-guide",
                                                "images": [
                                                    "https://cdn.example.com/media/guide.jpg"
                                                ],
                                                "video_url": ""
                                            },
                                            "linkedin": {
                                                "customized": false,
                                                "message": "Five ways to repurpose your best blog post",
                                                "title": "Repurposing guide",
                                                "description": "Turn one article into a week of social posts.",
                                                "url": "https://example.com/repurposing-guide",
                                                "images": [
                                                    "https://cdn.example.com/media/guide.jpg"
                                                ],
                                                "video_url": ""
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or does not decrypt to a post id.)\n\nContent not found. (The app returned no row for the post.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The post does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/add_content_in_library": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Add a recurring post to a content library.",
                "description": "Adds one post to the library in `id`. Library content is published again and again by the schedules attached to the library, so there is no post time here; `content_livedate` and `content_expiredate` bound when the post may go out and `is_top_of_queue` makes it the next one.\nThe content fields are the same as `/api/post_content`: `message`, `url`, `image_url` or `video_url`, and the per-network prefixed overrides. The post is saved as one tab per network from these fields. Two differences from one-off posts: a library post holds either images or a video, not both (`video_url` wins and `image_url` is ignored), and `twitter_thread` is not supported.\nThe post counts against the workspace owner's library content limit. The call does not return the new content id; read it from `/api/library_content_list`.\n\nImages or video, not both: When `video_url` is sent, `image_url` is ignored. `media_order` and `twitter_thread` are not read by the library calls.\n\nDates are plain days: `content_livedate` and `content_expiredate` are stored as dates in the workspace owner's timezone; any time part is discarded.\n\nPlan rules follow the workspace owner: The library content limit and the paid-plan check for video apply to the workspace owner's plan, not the caller's.\n\nOption checks: The option rules of `/api/post_content` (at most 20 images, 1000 characters of alt text, 3 collaborators, a location name with a location id, image tag positions) are checked here too and answer 400 before any media is fetched.\n\nBulk upload from a CSV: There is no CSV endpoint. The app's CSV import is this call applied once per row: map the sheet's columns to `message`, `url`, `image_url` or `video_url`, `content_livedate` and `content_expiredate`, and send one request per row into the same library `id`. Keep the calls sequential and inside your plan's per-minute allowance (see the rate-limit headers); a 429 says when to continue. Media must be public URLs or files from `/api/media_upload_url`.\n\nPer-network media: A network can post media of its own: `<prefix>_image_url` and `<prefix>_video_url` (`fb_`, `tw_`, `ln_`, `in_`, `gmb_`, `pi_`, `yt_`, `tk_`, `th_`, `bs_`) replace `image_url` / `video_url` on that network only and mark its tab as customised. Each network keeps its own cap (Facebook 15, Twitter/X 4, LinkedIn 20, Instagram 10 in all, Google Business 1, Pinterest 1, TikTok 10, Threads 20 in all, Bluesky 4); only Instagram and Threads combine images with a video, ordered by `in_media_order` / `th_media_order`; YouTube takes `yt_video_url` only. A URL named by several networks is downloaded once. Covers (`fb_thumb` and the others) apply to whichever video that network ends up with; `in_image_tags` and `in_product_tags` positions count in `in_image_url` when Instagram has its own images. Removing all media from one network is not possible: an empty override answers 400.\n\nLegacy endpoint: with body or Basic credentials errors arrive as HTTP 200 with the real status in the body field `status`. With a Bearer token it returns real HTTP status codes.",
                "operationId": "add_content_in_library",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted library id from `/api/library_list`. Exactly one.",
                                        "example": "lB7xK2mP9q=="
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "Post text. `\\r\\n` is normalised to `\\n`. The first link in it is used for the link preview when `url` is omitted.",
                                        "example": "Check out our latest product! https://example.com/product"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS9kLm2Qp1=="
                                    },
                                    "is_top_of_queue": {
                                        "type": "integer",
                                        "description": "`1` posts this content next on every account the library's schedules cover.",
                                        "enum": [
                                            0,
                                            1
                                        ],
                                        "default": "0",
                                        "example": 0
                                    },
                                    "content_livedate": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "First day the post may go out, `YYYY-MM-DD`; kept as a draft until then. A datetime like `2026-11-01T00:00:00+05:30` is accepted and cut to its date. Blank means active at once.",
                                        "example": "2026-11-01"
                                    },
                                    "content_expiredate": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Last day the post may go out, `YYYY-MM-DD`; recurring stops after it. A datetime is cut to its date. Blank means it never expires.",
                                        "example": "2026-12-31"
                                    },
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link to share with the post. On a text post the page's title, description and image are fetched and saved as the link preview; when omitted, the first link found in `message` is used instead. On a Pinterest account the value becomes the pin's destination link. `http://` is prepended when the scheme is missing. The host must be a public address.",
                                        "example": "https://example.com/summer-sale"
                                    },
                                    "image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Image URLs, in display order. Send a JSON array (or repeat `image_url[]` in form encoding); a single string is accepted as a one-item list. At most 20 images. Each URL must be a publicly reachable http or https URL and answer an image content type. URLs returned by `/api/media_upload_url` are used as they are; every other URL is copied to RecurPost storage unless `host_images_on_recurpost` is off. Ignored when `video_url` is also sent.",
                                        "example": [
                                            "https://example.com/sale1.jpg",
                                            "https://example.com/sale2.jpg"
                                        ]
                                    },
                                    "video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A public mp4 or mov URL (Google Drive share links are accepted and resolved to the download URL). The file is downloaded and stored on RecurPost storage, so the call takes as long as the download; a URL from `/api/media_upload_url` skips the download. Needs a paid plan. Files are limited to 2 GB.",
                                        "example": "https://example.com/promo.mp4"
                                    },
                                    "host_images_on_recurpost": {
                                        "type": "boolean",
                                        "description": "Copy images and custom thumbnails to RecurPost storage (the default). Send `false`, `0` or the form string `\"false\"` to keep your own URLs instead; they must then stay reachable until every post using them has been published.",
                                        "default": "true",
                                        "example": true
                                    },
                                    "alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text per image, in `image_url` order; a single string applies to the first image. At most 1000 characters each. Saved on the Facebook, Twitter/X, LinkedIn, Pinterest, Threads and Bluesky tabs; Instagram does not take alt text here.",
                                        "example": [
                                            "Two models in summer outfits",
                                            "Store front with sale banner"
                                        ]
                                    },
                                    "fb_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Facebook accounts instead of `image_url`, same rules and hosting as `image_url`. At most 15 images on Facebook. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `fb_video_url`.",
                                        "example": [
                                            "https://example.com/fb-square.jpg"
                                        ]
                                    },
                                    "fb_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Facebook accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `fb_image_url`.",
                                        "example": "https://example.com/fb-clip.mp4"
                                    },
                                    "fb_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `fb_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "tw_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Twitter/X accounts instead of `image_url`, same rules and hosting as `image_url`. At most 4 images on Twitter/X. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `tw_video_url`.",
                                        "example": [
                                            "https://example.com/tw-square.jpg"
                                        ]
                                    },
                                    "tw_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Twitter/X accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `tw_image_url`.",
                                        "example": "https://example.com/tw-clip.mp4"
                                    },
                                    "tw_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `tw_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "ln_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for LinkedIn accounts instead of `image_url`, same rules and hosting as `image_url`. At most 20 images on LinkedIn. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `ln_video_url`.",
                                        "example": [
                                            "https://example.com/ln-square.jpg"
                                        ]
                                    },
                                    "ln_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for LinkedIn accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `ln_image_url`.",
                                        "example": "https://example.com/ln-clip.mp4"
                                    },
                                    "ln_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `ln_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "in_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Instagram accounts instead of `image_url`, same rules and hosting as `image_url`. At most 10 media in all, images and video together on Instagram. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. May be combined with `in_video_url` into a carousel; `in_media_order` sets the order.",
                                        "example": [
                                            "https://example.com/in-square.jpg"
                                        ]
                                    },
                                    "in_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Instagram accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. May be combined with `in_image_url` into a carousel.",
                                        "example": "https://example.com/in-clip.mp4"
                                    },
                                    "in_media_order": {
                                        "type": "array",
                                        "items": [],
                                        "description": "The order of Instagram's own media as a list of the URLs given in `in_image_url` and `in_video_url`. Media left out of the list follow, video first. Only read when both are sent. Any other URL answers 400.",
                                        "example": [
                                            "https://example.com/in-clip.mp4",
                                            "https://example.com/in-square.jpg"
                                        ]
                                    },
                                    "gmb_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Google Business accounts instead of `image_url`, same rules and hosting as `image_url`. At most 1 image on Google Business. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `gmb_video_url`.",
                                        "example": [
                                            "https://example.com/gmb-square.jpg"
                                        ]
                                    },
                                    "gmb_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Google Business accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `gmb_image_url`.",
                                        "example": "https://example.com/gmb-clip.mp4"
                                    },
                                    "pi_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Pinterest accounts instead of `image_url`, same rules and hosting as `image_url`. At most 1 image on Pinterest. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `pi_video_url`.",
                                        "example": [
                                            "https://example.com/pi-square.jpg"
                                        ]
                                    },
                                    "pi_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Pinterest accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `pi_image_url`.",
                                        "example": "https://example.com/pi-clip.mp4"
                                    },
                                    "pi_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `pi_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "yt_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for YouTube accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. YouTube takes a video only, so there is no `yt_image_url`.",
                                        "example": "https://example.com/yt-clip.mp4"
                                    },
                                    "tk_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for TikTok accounts instead of `image_url`, same rules and hosting as `image_url`. At most 10 images on TikTok. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `tk_video_url`.",
                                        "example": [
                                            "https://example.com/tk-square.jpg"
                                        ]
                                    },
                                    "tk_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for TikTok accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `tk_image_url`.",
                                        "example": "https://example.com/tk-clip.mp4"
                                    },
                                    "th_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Threads accounts instead of `image_url`, same rules and hosting as `image_url`. At most 20 media in all, images and video together on Threads. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. May be combined with `th_video_url` into a carousel; `th_media_order` sets the order.",
                                        "example": [
                                            "https://example.com/th-square.jpg"
                                        ]
                                    },
                                    "th_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Threads accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. May be combined with `th_image_url` into a carousel.",
                                        "example": "https://example.com/th-clip.mp4"
                                    },
                                    "th_media_order": {
                                        "type": "array",
                                        "items": [],
                                        "description": "The order of Threads's own media as a list of the URLs given in `th_image_url` and `th_video_url`. Media left out of the list follow, video first. Only read when both are sent. Any other URL answers 400.",
                                        "example": [
                                            "https://example.com/th-clip.mp4",
                                            "https://example.com/th-square.jpg"
                                        ]
                                    },
                                    "th_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `th_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "bs_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Bluesky accounts instead of `image_url`, same rules and hosting as `image_url`. At most 4 images on Bluesky. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `bs_video_url`.",
                                        "example": [
                                            "https://example.com/bs-square.jpg"
                                        ]
                                    },
                                    "bs_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Bluesky accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `bs_image_url`.",
                                        "example": "https://example.com/bs-clip.mp4"
                                    },
                                    "bs_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `bs_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "fb_message": {
                                        "type": "string",
                                        "description": "Text for Facebook accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #facebook"
                                    },
                                    "tw_message": {
                                        "type": "string",
                                        "description": "Text for Twitter/X accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #twitter"
                                    },
                                    "ln_message": {
                                        "type": "string",
                                        "description": "Text for LinkedIn accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #linkedin"
                                    },
                                    "in_message": {
                                        "type": "string",
                                        "description": "Text for Instagram accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #instagram"
                                    },
                                    "gmb_message": {
                                        "type": "string",
                                        "description": "Text for Google Business accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #googlebusiness"
                                    },
                                    "pi_message": {
                                        "type": "string",
                                        "description": "Text for Pinterest accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #pinterest"
                                    },
                                    "yt_message": {
                                        "type": "string",
                                        "description": "Text for YouTube accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview. On YouTube this is the video description.",
                                        "example": "Summer sale is here! #youtube"
                                    },
                                    "tk_message": {
                                        "type": "string",
                                        "description": "Text for TikTok accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #tiktok"
                                    },
                                    "th_message": {
                                        "type": "string",
                                        "description": "Text for Threads accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #threads"
                                    },
                                    "bs_message": {
                                        "type": "string",
                                        "description": "Text for Bluesky accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #bluesky"
                                    },
                                    "first_comment": {
                                        "type": "string",
                                        "description": "First comment posted right after the post, commonly hashtags. Applied on Facebook Pages, LinkedIn and Instagram feed posts unless a network-specific first comment is given.",
                                        "example": "#summer #sale #deals"
                                    },
                                    "fb_first_comment": {
                                        "type": "string",
                                        "description": "Facebook first comment; overrides `first_comment` on Facebook.",
                                        "example": "#facebook #summersale"
                                    },
                                    "ln_first_comment": {
                                        "type": "string",
                                        "description": "LinkedIn first comment; overrides `first_comment` on LinkedIn.",
                                        "example": "#linkedin #summersale"
                                    },
                                    "in_first_comment": {
                                        "type": "string",
                                        "description": "Instagram first comment (feed posts only); overrides `first_comment` on Instagram.",
                                        "example": "#instagram #summersale"
                                    },
                                    "fb_post_type": {
                                        "type": "string",
                                        "description": "Facebook post type. Case-insensitive; an unknown value keeps `feed`.",
                                        "enum": [
                                            "feed",
                                            "reel",
                                            "story"
                                        ],
                                        "default": "feed",
                                        "example": "feed"
                                    },
                                    "fb_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Custom cover image URL for the video on Facebook. Public image URL; copied to RecurPost storage unless `host_images_on_recurpost` is off. Ignored when the post has no `video_url`.",
                                        "example": "https://example.com/fb-cover.jpg"
                                    },
                                    "ln_document": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public URL of a document to post as a LinkedIn document (carousel) post: PDF, PPT, PPTX, DOC or DOCX, detected from the file bytes, not the file name. The file is downloaded and stored on RecurPost storage and the LinkedIn tab becomes a document post. A file of another type is left as given and ignored by the publisher. Google Drive share links are resolved.",
                                        "example": "https://example.com/catalog.pdf"
                                    },
                                    "ln_document_title": {
                                        "type": "string",
                                        "description": "Title shown on the LinkedIn document. Defaults to the file name without its extension.",
                                        "example": "Summer Catalog 2026"
                                    },
                                    "ln_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Custom cover image URL for the video on LinkedIn. Ignored when the post has no `video_url`.",
                                        "example": "https://example.com/ln-cover.jpg"
                                    },
                                    "in_post_type": {
                                        "type": "string",
                                        "description": "Instagram post type. Case-insensitive; an unknown value keeps `feed`. A reel needs a `video_url`.",
                                        "enum": [
                                            "feed",
                                            "story",
                                            "reel"
                                        ],
                                        "default": "feed",
                                        "example": "feed"
                                    },
                                    "in_reel_share_in_feed": {
                                        "type": "string",
                                        "description": "Whether a reel also appears in the profile feed. Only read when `in_post_type` is `reel`.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "in_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Custom cover image URL for an Instagram reel. Only applied when `in_post_type` is `reel` and the post has a `video_url`; copied to RecurPost storage because Meta fetches it at publish time.",
                                        "example": "https://example.com/in-cover.jpg"
                                    },
                                    "in_location_id": {
                                        "type": "string",
                                        "description": "Instagram place id to tag the post with. Take `id` and `name` from `/api/instagram_locations`.",
                                        "example": "212988663"
                                    },
                                    "in_location_name": {
                                        "type": "string",
                                        "description": "Name of the place in `in_location_id`.",
                                        "example": "Pune, Maharashtra"
                                    },
                                    "in_location_city": {
                                        "type": "string",
                                        "description": "City of the tagged place, as returned by `/api/instagram_locations`.",
                                        "example": "Pune"
                                    },
                                    "in_location_country": {
                                        "type": "string",
                                        "description": "Country of the tagged place, as returned by `/api/instagram_locations`.",
                                        "example": "India"
                                    },
                                    "in_image_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "People to tag on feed images. A JSON array of objects with `username`, `x` and `y` (fractions of the image width and height between 0 and 1) and `image` (1-based position in `image_url`, default 1). The leading `@` is optional.",
                                        "example": [
                                            {
                                                "image": 1,
                                                "username": "recurpost",
                                                "x": 0.5,
                                                "y": 0.4
                                            }
                                        ]
                                    },
                                    "in_reel_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Usernames to tag on a reel, as a JSON array or a comma-separated string. Only saved when the post has a `video_url`.",
                                        "example": [
                                            "recurpost",
                                            "jane_doe"
                                        ]
                                    },
                                    "in_collaborators": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Instagram usernames invited as collaborators, as a JSON array or a comma-separated string. At most 3.",
                                        "example": [
                                            "jane_doe"
                                        ]
                                    },
                                    "pi_title": {
                                        "type": "string",
                                        "description": "Pin title. The destination link of the pin is `url` or the first link in the text.",
                                        "example": "Summer Sale - Best Deals of the Season"
                                    },
                                    "gbp_cta": {
                                        "type": "string",
                                        "description": "Call-to-action button on the Google Business post. Case-insensitive. An unknown value or `None` saves no button. On a link post with no CTA given, `Learn more` pointing at the link is set automatically.",
                                        "enum": [
                                            "Learn more",
                                            "Sign up",
                                            "Buy",
                                            "Order online",
                                            "Book",
                                            "Call now",
                                            "Offer",
                                            "None"
                                        ],
                                        "default": "None",
                                        "example": "Learn more"
                                    },
                                    "gbp_cta_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link the button opens. Not used for `Call now`. With `gbp_cta=Offer` and no `gbp_redeem_offer_link`, this value doubles as the redeem link.",
                                        "example": "https://example.com/summer-sale"
                                    },
                                    "gbp_offer_title": {
                                        "type": "string",
                                        "description": "Offer title; offer fields are used when `gbp_cta` is `Offer`.",
                                        "example": "Summer Sale - 50% Off"
                                    },
                                    "gbp_offer_start_date": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Offer start, `YYYY-MM-DD HH:MM:SS`.",
                                        "example": "2026-06-01 00:00:00"
                                    },
                                    "gbp_offer_end_date": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Offer end, `YYYY-MM-DD HH:MM:SS`.",
                                        "example": "2026-06-30 23:59:59"
                                    },
                                    "gbp_offer_coupon_code": {
                                        "type": "string",
                                        "description": "Coupon code shown on the offer.",
                                        "example": "SUMMER50"
                                    },
                                    "gbp_offer_terms": {
                                        "type": "string",
                                        "description": "Terms and conditions of the offer.",
                                        "example": "Valid on selected items only"
                                    },
                                    "gbp_redeem_offer_link": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link to redeem the offer.",
                                        "example": "https://example.com/redeem"
                                    },
                                    "yt_title": {
                                        "type": "string",
                                        "description": "Video title. YouTube needs a `video_url`; `message` or `yt_message` is the description.",
                                        "example": "Summer Sale Announcement 2026"
                                    },
                                    "yt_category": {
                                        "type": "string",
                                        "description": "Category name, matched exactly against the list. An unknown or missing name falls back to the default category of the workspace owner's YouTube settings (Entertainment when none is set).",
                                        "enum": [
                                            "Film & Animation",
                                            "Autos & Vehicles",
                                            "Music",
                                            "Pets & Animals",
                                            "Sports",
                                            "Travel & Events",
                                            "Gaming",
                                            "People & Blogs",
                                            "Comedy",
                                            "Entertainment",
                                            "News & Politics",
                                            "Howto & Style",
                                            "Education",
                                            "Science & Technology",
                                            "Nonprofits & Activism"
                                        ],
                                        "example": "Howto & Style"
                                    },
                                    "yt_privacy_status": {
                                        "type": "string",
                                        "description": "Video privacy. Lower-cased and stored as given; use one of the listed values.",
                                        "enum": [
                                            "public",
                                            "private",
                                            "unlisted"
                                        ],
                                        "default": "public",
                                        "example": "public"
                                    },
                                    "yt_user_tags": {
                                        "type": "string",
                                        "description": "Video tags, comma-separated.",
                                        "example": "summer, sale, deals"
                                    },
                                    "yt_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Custom thumbnail URL for the YouTube video. Public image URL; copied to RecurPost storage unless `host_images_on_recurpost` is off.",
                                        "example": "https://example.com/yt-thumb.jpg"
                                    },
                                    "yt_video_made_for_kids": {
                                        "type": "string",
                                        "description": "Whether the video is made for kids. Only `yes` switches it on.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "no",
                                        "example": "no"
                                    },
                                    "tk_privacy_status": {
                                        "type": "string",
                                        "description": "Who can watch the TikTok video. Case-insensitive, spaces or underscores. Any other value is saved as `Public to Everyone`; omitted leaves it unset. `/api/tiktok_options` lists what the account allows.",
                                        "enum": [
                                            "Public to Everyone",
                                            "Mutual Follow Friends",
                                            "Self Only"
                                        ],
                                        "example": "Public to Everyone"
                                    },
                                    "tk_allow_comments": {
                                        "type": "string",
                                        "description": "Allow comments on the TikTok video. Only `no` switches it off.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_allow_duet": {
                                        "type": "string",
                                        "description": "Allow duets. Only `no` switches it off.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_allow_stitches": {
                                        "type": "string",
                                        "description": "Allow stitches. Only `no` switches it off.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_promote_own_brand": {
                                        "type": "integer",
                                        "description": "Set to `1` to mark the video as promoting your own brand (TikTok's content disclosure).",
                                        "enum": [
                                            0,
                                            1
                                        ],
                                        "default": "0",
                                        "example": 0
                                    },
                                    "tk_promote_other_brand": {
                                        "type": "integer",
                                        "description": "Set to `1` to mark the video as branded content for a third party.",
                                        "enum": [
                                            0,
                                            1
                                        ],
                                        "default": "0",
                                        "example": 0
                                    }
                                },
                                "required": [
                                    "id",
                                    "message"
                                ],
                                "example": {
                                    "id": "lB7xK2mP9q==",
                                    "message": "Check out our latest product! https://example.com/product"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Content added successfully`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Content added successfully"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (message blank, or id missing / not decryptable to one library id.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\n<message from the app> (The library save failed for another reason; the app's text is relayed.)\n\nimage_url takes at most 20 images. (More than 20 image URLs.)\n\nalt_text entries may have at most 1000 characters. (An alt_text entry is longer than 1000 characters.)\n\nin_location_name is required with in_location_id; both come from instagram_locations. (in_location_id without in_location_name.)\n\nin_collaborators takes at most 3 usernames. (More than 3 collaborators.)\n\nin_reel_tags needs a video_url. (in_reel_tags sent on a post without a video.)\n\nin_image_tags entries need username, x and y between 0 and 1, and image as a position in image_url. (An in_image_tags entry is malformed or points past the last image.)\n\nmedia_order may only hold the URLs given in image_url and video_url. (media_order names a URL that is not in the post.)\n\ntwitter_thread takes at most 25 further tweets. (More than 25 thread items.)\n\n<prefix>_image_url / <prefix>_video_url must leave <network> at least one image or a video. (A per-network media field is sent empty.)\n\nyt_image_url is not accepted; YouTube takes yt_video_url only. (Images sent for YouTube.)\n\n<prefix>_image_url and <prefix>_video_url cannot be combined; only Instagram and Threads take images and a video together. (Images and a video for one network other than Instagram or Threads.)\n\n<prefix>_image_url takes at most <n> images for <network>. (More images than that network allows. Instagram and Threads count images and video together and answer \"_image_url and _video_url take at most  media items together for .\")\n\n<prefix>_media_order may only hold the URLs given in <prefix>_image_url and <prefix>_video_url. (A per-network order names a URL outside that network's own media.)\n\n<prefix>_alt_text entries may have at most 1000 characters. (A per-network alt text entry is longer than 1000 characters.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library does not belong to the workspace owner.)\n\nThe limit of the user's RecurPost plan has exhausted. (The workspace owner's library content count has reached the plan limit.)\n\nYou are not allowed to upload video file in your current plan. Please upgrade your RecurPost plan. (video_url sent while the workspace owner is on a free plan.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not one of your workspaces or your membership is not active.)\n\nThis library is not part of the selected workspace. (The library is the owner's but not in the named workspace_id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Media URL is not allowed: <url>. Please supply a publicly reachable http or https URL. (An image_url, video_url, thumbnail, ln_document or thread media URL is not http/https or its host resolves to a private, loopback or reserved address.)\n\nInvalid url parameter supplied (url (or the first link in the text) is not a valid public URL.)\n\nURL is not a video (detected content type: <type>). Please supply a valid video URL. (video_url answers a non-video content type.)\n\nInvalid video format (detected: <type>). Supported formats: mp4, mov (video_url is neither mp4 nor mov by extension or content type.)\n\nThe media URL could not be downloaded. (video_url or ln_document could not be read.)\n\nFailed to upload video. The URL was reachable but the file could not be processed. (The downloaded video was refused by storage (size over 2 GB, unreadable file).)\n\nURL is not an image (detected content type: <type>). Please supply a valid image URL. (An image_url answers a non-image content type.)\n\nInvalid image url parameter supplied. The URL did not return a recognizable image. (An image_url could not be read as an image.)\n\nFailed to upload image. The URL was reachable but the file could not be processed. (The image could not be stored.)\n\nInvalid <param> parameter supplied. The URL did not return a recognizable image. (fb_thumb, in_thumb, ln_thumb or yt_thumb is not an image (only checked on video posts with hosting on).)\n\nFailed to upload <param>. The URL was reachable but the file could not be processed. (A thumbnail could not be stored.)\n\nThe uploaded file at <url> is missing or is not a <image|video> (detected <type>). (A media_upload_url URL was never PUT to, or was PUT with the wrong Content-Type.)\n\nFiles are limited to 2 GB. (A media_upload_url object is larger than 2 GB.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Content validation failed! (The app's content validator refused one or more network tabs (text too long, media that the network does not accept, a reel without video, ...). The body carries `error_details`, an object keyed by network with the reason.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_content_update": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Replace the text, media and network options of a library post.",
                "description": "Rewrites the library post `id` inside library `library_id` with the fields of the request. It takes the same fields as `/api/add_content_in_library`; every network tab is rebuilt from what you send, so fields you leave out are reset to their defaults, not kept. Send the whole post each time.\nThe post keeps its id and its place in the library; `content_livedate`, `content_expiredate` and `is_top_of_queue` are written from the request too.\n\nFull replacement: This is not a patch. Media, per-network messages, first comments, covers and options not present in the request are dropped; images already on RecurPost storage must be sent again by their URL (they are kept as they are, nothing is re-downloaded).\n\nOption checks: The option rules of `/api/post_content` (at most 20 images, 1000 characters of alt text, 3 collaborators, a location name with a location id, image tag positions) are checked here too and answer 400 before any media is fetched.\n\nmedia_order and twitter_thread are checked but not applied: `media_order` and `twitter_thread` pass the option checks above (and answer their 400s when malformed) but have no effect on a library post: the library builder never makes a mixed post (a `video_url` wins over `image_url`, so there is no media order) and never builds thread tabs. Threads and mixed media are one-off features of `/api/post_content` and `/api/queue_post_update`.\n\nPer-network media: A network can post media of its own: `<prefix>_image_url` and `<prefix>_video_url` (`fb_`, `tw_`, `ln_`, `in_`, `gmb_`, `pi_`, `yt_`, `tk_`, `th_`, `bs_`) replace `image_url` / `video_url` on that network only and mark its tab as customised. Each network keeps its own cap (Facebook 15, Twitter/X 4, LinkedIn 20, Instagram 10 in all, Google Business 1, Pinterest 1, TikTok 10, Threads 20 in all, Bluesky 4); only Instagram and Threads combine images with a video, ordered by `in_media_order` / `th_media_order`; YouTube takes `yt_video_url` only. A URL named by several networks is downloaded once. Covers (`fb_thumb` and the others) apply to whichever video that network ends up with; `in_image_tags` and `in_product_tags` positions count in `in_image_url` when Instagram has its own images. Removing all media from one network is not possible: an empty override answers 400.",
                "operationId": "library_content_update",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted library id the post belongs to, from `/api/library_list`.",
                                        "example": "lB7xK2mP9q=="
                                    },
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted library content id from `/api/library_content_list`.",
                                        "example": "cN4vR8tY1z=="
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "New post text. `\\r\\n` is normalised to `\\n`.",
                                        "example": "Updated: our latest product is now 20% off! https://example.com/product"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS9kLm2Qp1=="
                                    },
                                    "is_top_of_queue": {
                                        "type": "integer",
                                        "description": "`1` posts this content next on every account the library's schedules cover.",
                                        "enum": [
                                            0,
                                            1
                                        ],
                                        "default": "0",
                                        "example": 0
                                    },
                                    "content_livedate": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "First day the post may go out, `YYYY-MM-DD`. Blank clears it.",
                                        "example": "2026-11-01"
                                    },
                                    "content_expiredate": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Last day the post may go out, `YYYY-MM-DD`. Blank clears it.",
                                        "example": "2026-12-31"
                                    },
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link to share with the post. On a text post the page's title, description and image are fetched and saved as the link preview; when omitted, the first link found in `message` is used instead. On a Pinterest account the value becomes the pin's destination link. `http://` is prepended when the scheme is missing. The host must be a public address.",
                                        "example": "https://example.com/summer-sale"
                                    },
                                    "image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Image URLs, in display order. Send a JSON array (or repeat `image_url[]` in form encoding); a single string is accepted as a one-item list. At most 20 images. Each URL must be a publicly reachable http or https URL and answer an image content type. URLs returned by `/api/media_upload_url` are used as they are; every other URL is copied to RecurPost storage unless `host_images_on_recurpost` is off. Ignored when `video_url` is also sent.",
                                        "example": [
                                            "https://example.com/sale1.jpg",
                                            "https://example.com/sale2.jpg"
                                        ]
                                    },
                                    "video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A public mp4 or mov URL (Google Drive share links are accepted and resolved to the download URL). The file is downloaded and stored on RecurPost storage, so the call takes as long as the download; a URL from `/api/media_upload_url` skips the download. Needs a paid plan. Files are limited to 2 GB.",
                                        "example": "https://example.com/promo.mp4"
                                    },
                                    "host_images_on_recurpost": {
                                        "type": "boolean",
                                        "description": "Copy images and custom thumbnails to RecurPost storage (the default). Send `false`, `0` or the form string `\"false\"` to keep your own URLs instead; they must then stay reachable until every post using them has been published.",
                                        "default": "true",
                                        "example": true
                                    },
                                    "alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text per image, in `image_url` order; a single string applies to the first image. At most 1000 characters each. Saved on the Facebook, Twitter/X, LinkedIn, Pinterest, Threads and Bluesky tabs; Instagram does not take alt text here.",
                                        "example": [
                                            "Two models in summer outfits",
                                            "Store front with sale banner"
                                        ]
                                    },
                                    "fb_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Facebook accounts instead of `image_url`, same rules and hosting as `image_url`. At most 15 images on Facebook. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `fb_video_url`.",
                                        "example": [
                                            "https://example.com/fb-square.jpg"
                                        ]
                                    },
                                    "fb_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Facebook accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `fb_image_url`.",
                                        "example": "https://example.com/fb-clip.mp4"
                                    },
                                    "fb_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `fb_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "tw_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Twitter/X accounts instead of `image_url`, same rules and hosting as `image_url`. At most 4 images on Twitter/X. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `tw_video_url`.",
                                        "example": [
                                            "https://example.com/tw-square.jpg"
                                        ]
                                    },
                                    "tw_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Twitter/X accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `tw_image_url`.",
                                        "example": "https://example.com/tw-clip.mp4"
                                    },
                                    "tw_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `tw_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "ln_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for LinkedIn accounts instead of `image_url`, same rules and hosting as `image_url`. At most 20 images on LinkedIn. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `ln_video_url`.",
                                        "example": [
                                            "https://example.com/ln-square.jpg"
                                        ]
                                    },
                                    "ln_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for LinkedIn accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `ln_image_url`.",
                                        "example": "https://example.com/ln-clip.mp4"
                                    },
                                    "ln_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `ln_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "in_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Instagram accounts instead of `image_url`, same rules and hosting as `image_url`. At most 10 media in all, images and video together on Instagram. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. May be combined with `in_video_url` into a carousel; `in_media_order` sets the order.",
                                        "example": [
                                            "https://example.com/in-square.jpg"
                                        ]
                                    },
                                    "in_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Instagram accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. May be combined with `in_image_url` into a carousel.",
                                        "example": "https://example.com/in-clip.mp4"
                                    },
                                    "in_media_order": {
                                        "type": "array",
                                        "items": [],
                                        "description": "The order of Instagram's own media as a list of the URLs given in `in_image_url` and `in_video_url`. Media left out of the list follow, video first. Only read when both are sent. Any other URL answers 400.",
                                        "example": [
                                            "https://example.com/in-clip.mp4",
                                            "https://example.com/in-square.jpg"
                                        ]
                                    },
                                    "gmb_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Google Business accounts instead of `image_url`, same rules and hosting as `image_url`. At most 1 image on Google Business. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `gmb_video_url`.",
                                        "example": [
                                            "https://example.com/gmb-square.jpg"
                                        ]
                                    },
                                    "gmb_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Google Business accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `gmb_image_url`.",
                                        "example": "https://example.com/gmb-clip.mp4"
                                    },
                                    "pi_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Pinterest accounts instead of `image_url`, same rules and hosting as `image_url`. At most 1 image on Pinterest. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `pi_video_url`.",
                                        "example": [
                                            "https://example.com/pi-square.jpg"
                                        ]
                                    },
                                    "pi_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Pinterest accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `pi_image_url`.",
                                        "example": "https://example.com/pi-clip.mp4"
                                    },
                                    "pi_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `pi_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "yt_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for YouTube accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. YouTube takes a video only, so there is no `yt_image_url`.",
                                        "example": "https://example.com/yt-clip.mp4"
                                    },
                                    "tk_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for TikTok accounts instead of `image_url`, same rules and hosting as `image_url`. At most 10 images on TikTok. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `tk_video_url`.",
                                        "example": [
                                            "https://example.com/tk-square.jpg"
                                        ]
                                    },
                                    "tk_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for TikTok accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `tk_image_url`.",
                                        "example": "https://example.com/tk-clip.mp4"
                                    },
                                    "th_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Threads accounts instead of `image_url`, same rules and hosting as `image_url`. At most 20 media in all, images and video together on Threads. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. May be combined with `th_video_url` into a carousel; `th_media_order` sets the order.",
                                        "example": [
                                            "https://example.com/th-square.jpg"
                                        ]
                                    },
                                    "th_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Threads accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. May be combined with `th_image_url` into a carousel.",
                                        "example": "https://example.com/th-clip.mp4"
                                    },
                                    "th_media_order": {
                                        "type": "array",
                                        "items": [],
                                        "description": "The order of Threads's own media as a list of the URLs given in `th_image_url` and `th_video_url`. Media left out of the list follow, video first. Only read when both are sent. Any other URL answers 400.",
                                        "example": [
                                            "https://example.com/th-clip.mp4",
                                            "https://example.com/th-square.jpg"
                                        ]
                                    },
                                    "th_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `th_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "bs_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Bluesky accounts instead of `image_url`, same rules and hosting as `image_url`. At most 4 images on Bluesky. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `bs_video_url`.",
                                        "example": [
                                            "https://example.com/bs-square.jpg"
                                        ]
                                    },
                                    "bs_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Bluesky accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `bs_image_url`.",
                                        "example": "https://example.com/bs-clip.mp4"
                                    },
                                    "bs_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `bs_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "fb_message": {
                                        "type": "string",
                                        "description": "Text for Facebook accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #facebook"
                                    },
                                    "tw_message": {
                                        "type": "string",
                                        "description": "Text for Twitter/X accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #twitter"
                                    },
                                    "ln_message": {
                                        "type": "string",
                                        "description": "Text for LinkedIn accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #linkedin"
                                    },
                                    "in_message": {
                                        "type": "string",
                                        "description": "Text for Instagram accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #instagram"
                                    },
                                    "gmb_message": {
                                        "type": "string",
                                        "description": "Text for Google Business accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #googlebusiness"
                                    },
                                    "pi_message": {
                                        "type": "string",
                                        "description": "Text for Pinterest accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #pinterest"
                                    },
                                    "yt_message": {
                                        "type": "string",
                                        "description": "Text for YouTube accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview. On YouTube this is the video description.",
                                        "example": "Summer sale is here! #youtube"
                                    },
                                    "tk_message": {
                                        "type": "string",
                                        "description": "Text for TikTok accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #tiktok"
                                    },
                                    "th_message": {
                                        "type": "string",
                                        "description": "Text for Threads accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #threads"
                                    },
                                    "bs_message": {
                                        "type": "string",
                                        "description": "Text for Bluesky accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #bluesky"
                                    },
                                    "first_comment": {
                                        "type": "string",
                                        "description": "First comment posted right after the post, commonly hashtags. Applied on Facebook Pages, LinkedIn and Instagram feed posts unless a network-specific first comment is given.",
                                        "example": "#summer #sale #deals"
                                    },
                                    "fb_first_comment": {
                                        "type": "string",
                                        "description": "Facebook first comment; overrides `first_comment` on Facebook.",
                                        "example": "#facebook #summersale"
                                    },
                                    "fb_mentions": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Facebook pages to mention, at most 10: page ids from `/api/mention_search`, as a list of ids or of `{page_id, name}` objects. Write each page in the text as `@<page id>`; the publisher turns it into the page's mention on Facebook pages.",
                                        "example": [
                                            {
                                                "page_id": "108296975869040",
                                                "name": "Acme"
                                            }
                                        ]
                                    },
                                    "fb_background_id": {
                                        "type": "string",
                                        "description": "Facebook text background for a post without `image_url` or `video_url`: an id from `/api/facebook_backgrounds` (letters, digits, underscore or dash, up to 64 characters). Applied on Facebook pages only.",
                                        "example": "106"
                                    },
                                    "ln_first_comment": {
                                        "type": "string",
                                        "description": "LinkedIn first comment; overrides `first_comment` on LinkedIn.",
                                        "example": "#linkedin #summersale"
                                    },
                                    "in_first_comment": {
                                        "type": "string",
                                        "description": "Instagram first comment (feed posts only); overrides `first_comment` on Instagram.",
                                        "example": "#instagram #summersale"
                                    },
                                    "fb_post_type": {
                                        "type": "string",
                                        "description": "Facebook post type. Case-insensitive; an unknown value keeps `feed`.",
                                        "enum": [
                                            "feed",
                                            "reel",
                                            "story"
                                        ],
                                        "default": "feed",
                                        "example": "feed"
                                    },
                                    "fb_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Custom cover image URL for the video on Facebook. Public image URL; copied to RecurPost storage unless `host_images_on_recurpost` is off. Ignored when the post has no `video_url`.",
                                        "example": "https://example.com/fb-cover.jpg"
                                    },
                                    "ln_document": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public URL of a document to post as a LinkedIn document (carousel) post: PDF, PPT, PPTX, DOC or DOCX, detected from the file bytes, not the file name. The file is downloaded and stored on RecurPost storage and the LinkedIn tab becomes a document post. A file of another type is left as given and ignored by the publisher. Google Drive share links are resolved.",
                                        "example": "https://example.com/catalog.pdf"
                                    },
                                    "ln_document_title": {
                                        "type": "string",
                                        "description": "Title shown on the LinkedIn document. Defaults to the file name without its extension.",
                                        "example": "Summer Catalog 2026"
                                    },
                                    "ln_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Custom cover image URL for the video on LinkedIn. Ignored when the post has no `video_url`.",
                                        "example": "https://example.com/ln-cover.jpg"
                                    },
                                    "in_post_type": {
                                        "type": "string",
                                        "description": "Instagram post type. Case-insensitive; an unknown value keeps `feed`. A reel needs a `video_url`.",
                                        "enum": [
                                            "feed",
                                            "story",
                                            "reel"
                                        ],
                                        "default": "feed",
                                        "example": "feed"
                                    },
                                    "in_reel_share_in_feed": {
                                        "type": "string",
                                        "description": "Whether a reel also appears in the profile feed. Only read when `in_post_type` is `reel`.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "in_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Custom cover image URL for an Instagram reel. Only applied when `in_post_type` is `reel` and the post has a `video_url`; copied to RecurPost storage because Meta fetches it at publish time.",
                                        "example": "https://example.com/in-cover.jpg"
                                    },
                                    "in_location_id": {
                                        "type": "string",
                                        "description": "Instagram place id to tag the post with. Take `id` and `name` from `/api/instagram_locations`.",
                                        "example": "212988663"
                                    },
                                    "in_location_name": {
                                        "type": "string",
                                        "description": "Name of the place in `in_location_id`.",
                                        "example": "Pune, Maharashtra"
                                    },
                                    "in_location_city": {
                                        "type": "string",
                                        "description": "City of the tagged place, as returned by `/api/instagram_locations`.",
                                        "example": "Pune"
                                    },
                                    "in_location_country": {
                                        "type": "string",
                                        "description": "Country of the tagged place, as returned by `/api/instagram_locations`.",
                                        "example": "India"
                                    },
                                    "in_image_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "People to tag on feed images. A JSON array of objects with `username`, `x` and `y` (fractions of the image width and height between 0 and 1) and `image` (1-based position in `image_url`, default 1). The leading `@` is optional.",
                                        "example": [
                                            {
                                                "image": 1,
                                                "username": "recurpost",
                                                "x": 0.5,
                                                "y": 0.4
                                            }
                                        ]
                                    },
                                    "in_reel_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Usernames to tag on a reel, as a JSON array or a comma-separated string. Only saved when the post has a `video_url`.",
                                        "example": [
                                            "recurpost",
                                            "jane_doe"
                                        ]
                                    },
                                    "in_collaborators": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Instagram usernames invited as collaborators, as a JSON array or a comma-separated string. At most 3.",
                                        "example": [
                                            "jane_doe"
                                        ]
                                    },
                                    "in_audio_id": {
                                        "type": "string",
                                        "description": "Instagram audio to lay under a reel, from `/api/instagram_audio_search`. Needs `in_post_type` reel, a `video_url` and `in_audio_account_id`.",
                                        "example": "1234567890123456"
                                    },
                                    "in_audio_account_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the Instagram account `/api/instagram_audio_search` ran for. Required with `in_audio_id`.",
                                        "example": "aK3mZ8vQr1=="
                                    },
                                    "in_audio_type": {
                                        "type": "string",
                                        "description": "Kind of audio behind `in_audio_id`.",
                                        "enum": [
                                            "music",
                                            "original_sound"
                                        ],
                                        "default": "music",
                                        "example": "music"
                                    },
                                    "in_audio_title": {
                                        "type": "string",
                                        "description": "Title of the audio, as the search returned it; stored with the reel.",
                                        "example": "Summer Nights"
                                    },
                                    "in_audio_artist": {
                                        "type": "string",
                                        "description": "Artist of the audio, as the search returned it.",
                                        "example": "The Examples"
                                    },
                                    "in_audio_duration_ms": {
                                        "type": "integer",
                                        "description": "Length of the audio in milliseconds, as the search returned it.",
                                        "example": 30000
                                    },
                                    "in_audio_volume": {
                                        "type": "integer",
                                        "description": "Volume of the added audio, 0 to 100.",
                                        "default": "100",
                                        "example": 100
                                    },
                                    "in_video_volume": {
                                        "type": "integer",
                                        "description": "Volume of the reel's own sound, 0 to 100.",
                                        "default": "100",
                                        "example": 100
                                    },
                                    "in_trial_reel": {
                                        "type": "string",
                                        "description": "Publish the reel as a trial reel, shown to non-followers first. `manual`: you decide in Instagram when to share it with followers; `performance`: Instagram shares it when it does well. Reels only.",
                                        "enum": [
                                            "manual",
                                            "performance"
                                        ],
                                        "example": "manual"
                                    },
                                    "in_product_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Instagram product tags on images: objects with `account_id` (encrypted, the account whose catalog holds the product), `product_id` (from `/api/instagram_products`), `image` (1-based position in `image_url`), `x` and `y` (0 to 1, default 0.5), and optionally `product_name` and `product_image`.",
                                        "example": [
                                            {
                                                "image": 1,
                                                "account_id": "aK3mZ8vQr1==",
                                                "product_id": "901000111222333",
                                                "x": 0.5,
                                                "y": 0.6
                                            }
                                        ]
                                    },
                                    "in_reel_product_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Products tagged on a reel: objects with `account_id` (encrypted) and `product_id` (from `/api/instagram_products`), optionally `product_name` and `image_url`. Reels only.",
                                        "example": [
                                            {
                                                "account_id": "aK3mZ8vQr1==",
                                                "product_id": "901000111222333"
                                            }
                                        ]
                                    },
                                    "pi_title": {
                                        "type": "string",
                                        "description": "Pin title. The destination link of the pin is `url` or the first link in the text.",
                                        "example": "Summer Sale - Best Deals of the Season"
                                    },
                                    "gbp_cta": {
                                        "type": "string",
                                        "description": "Call-to-action button on the Google Business post. Case-insensitive. An unknown value or `None` saves no button. On a link post with no CTA given, `Learn more` pointing at the link is set automatically.",
                                        "enum": [
                                            "Learn more",
                                            "Sign up",
                                            "Buy",
                                            "Order online",
                                            "Book",
                                            "Call now",
                                            "Offer",
                                            "None"
                                        ],
                                        "default": "None",
                                        "example": "Learn more"
                                    },
                                    "gbp_cta_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link the button opens. Not used for `Call now`. With `gbp_cta=Offer` and no `gbp_redeem_offer_link`, this value doubles as the redeem link.",
                                        "example": "https://example.com/summer-sale"
                                    },
                                    "gbp_offer_title": {
                                        "type": "string",
                                        "description": "Offer title; offer fields are used when `gbp_cta` is `Offer`.",
                                        "example": "Summer Sale - 50% Off"
                                    },
                                    "gbp_offer_start_date": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Offer start, `YYYY-MM-DD HH:MM:SS`.",
                                        "example": "2026-06-01 00:00:00"
                                    },
                                    "gbp_offer_end_date": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Offer end, `YYYY-MM-DD HH:MM:SS`.",
                                        "example": "2026-06-30 23:59:59"
                                    },
                                    "gbp_offer_coupon_code": {
                                        "type": "string",
                                        "description": "Coupon code shown on the offer.",
                                        "example": "SUMMER50"
                                    },
                                    "gbp_offer_terms": {
                                        "type": "string",
                                        "description": "Terms and conditions of the offer.",
                                        "example": "Valid on selected items only"
                                    },
                                    "gbp_redeem_offer_link": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link to redeem the offer.",
                                        "example": "https://example.com/redeem"
                                    },
                                    "yt_title": {
                                        "type": "string",
                                        "description": "Video title. YouTube needs a `video_url`; `message` or `yt_message` is the description.",
                                        "example": "Summer Sale Announcement 2026"
                                    },
                                    "yt_category": {
                                        "type": "string",
                                        "description": "Category name, matched exactly against the list. An unknown or missing name falls back to the default category of the workspace owner's YouTube settings (Entertainment when none is set).",
                                        "enum": [
                                            "Film & Animation",
                                            "Autos & Vehicles",
                                            "Music",
                                            "Pets & Animals",
                                            "Sports",
                                            "Travel & Events",
                                            "Gaming",
                                            "People & Blogs",
                                            "Comedy",
                                            "Entertainment",
                                            "News & Politics",
                                            "Howto & Style",
                                            "Education",
                                            "Science & Technology",
                                            "Nonprofits & Activism"
                                        ],
                                        "example": "Howto & Style"
                                    },
                                    "yt_privacy_status": {
                                        "type": "string",
                                        "description": "Video privacy. Lower-cased and stored as given; use one of the listed values.",
                                        "enum": [
                                            "public",
                                            "private",
                                            "unlisted"
                                        ],
                                        "default": "public",
                                        "example": "public"
                                    },
                                    "yt_user_tags": {
                                        "type": "string",
                                        "description": "Video tags, comma-separated.",
                                        "example": "summer, sale, deals"
                                    },
                                    "yt_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Custom thumbnail URL for the YouTube video. Public image URL; copied to RecurPost storage unless `host_images_on_recurpost` is off.",
                                        "example": "https://example.com/yt-thumb.jpg"
                                    },
                                    "yt_video_made_for_kids": {
                                        "type": "string",
                                        "description": "Whether the video is made for kids. Only `yes` switches it on.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "no",
                                        "example": "no"
                                    },
                                    "tk_privacy_status": {
                                        "type": "string",
                                        "description": "Who can watch the TikTok video. Case-insensitive, spaces or underscores. Any other value is saved as `Public to Everyone`; omitted leaves it unset. `/api/tiktok_options` lists what the account allows.",
                                        "enum": [
                                            "Public to Everyone",
                                            "Mutual Follow Friends",
                                            "Self Only"
                                        ],
                                        "example": "Public to Everyone"
                                    },
                                    "tk_allow_comments": {
                                        "type": "string",
                                        "description": "Allow comments on the TikTok video. Only `no` switches it off.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_allow_duet": {
                                        "type": "string",
                                        "description": "Allow duets. Only `no` switches it off.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_allow_stitches": {
                                        "type": "string",
                                        "description": "Allow stitches. Only `no` switches it off.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_promote_own_brand": {
                                        "type": "integer",
                                        "description": "Set to `1` to mark the video as promoting your own brand (TikTok's content disclosure).",
                                        "enum": [
                                            0,
                                            1
                                        ],
                                        "default": "0",
                                        "example": 0
                                    },
                                    "tk_promote_other_brand": {
                                        "type": "integer",
                                        "description": "Set to `1` to mark the video as branded content for a third party.",
                                        "enum": [
                                            0,
                                            1
                                        ],
                                        "default": "0",
                                        "example": 0
                                    }
                                },
                                "required": [
                                    "library_id",
                                    "id",
                                    "message"
                                ],
                                "example": {
                                    "library_id": "lB7xK2mP9q==",
                                    "id": "cN4vR8tY1z==",
                                    "message": "Updated: our latest product is now 20% off! https://example.com/product"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Content updated successfully`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Content updated successfully"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (message blank, or library_id / id missing or not decryptable.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\n<message from the app> (The update failed for another reason (for example the content is not in that library); the app's text is relayed.)\n\nimage_url takes at most 20 images. (More than 20 image URLs.)\n\nalt_text entries may have at most 1000 characters. (An alt_text entry is longer than 1000 characters.)\n\nin_location_name is required with in_location_id; both come from instagram_locations. (in_location_id without in_location_name.)\n\nin_collaborators takes at most 3 usernames. (More than 3 collaborators.)\n\nin_reel_tags needs a video_url. (in_reel_tags sent on a post without a video.)\n\nin_image_tags entries need username, x and y between 0 and 1, and image as a position in image_url. (An in_image_tags entry is malformed or points past the last image.)\n\nmedia_order may only hold the URLs given in image_url and video_url. (media_order names a URL that is not in the post.)\n\ntwitter_thread takes at most 25 further tweets. (More than 25 thread items.)\n\nin_audio_id needs in_post_type reel with a video_url, in_audio_account_id (the account instagram_audio_search ran for), in_audio_type music or original_sound, and volumes from 0 to 100. (in_audio_id is sent without those conditions.)\n\nin_trial_reel is manual or performance, on in_post_type reel only. (in_trial_reel has another value or the post is not a reel.)\n\nin_product_tags entries need account_id, product_id (from instagram_products), image as a position in image_url, and x and y between 0 and 1. (An in_product_tags entry is malformed or points past the last image.)\n\nin_reel_product_tags entries need account_id and product_id, on in_post_type reel only. (An in_reel_product_tags entry is malformed or the post is not a reel.)\n\nfb_mentions holds page ids from mention_search, as a list or as {page_id, name} items. (An fb_mentions entry is not a numeric page id.)\n\nfb_mentions takes at most 10 pages. (More than 10 pages in fb_mentions.)\n\nfb_background_id takes a background id from facebook_backgrounds, on a post without image_url or video_url. (fb_background_id is sent with media, or is not a plain id.)\n\n<prefix>_image_url / <prefix>_video_url must leave <network> at least one image or a video. (A per-network media field is sent empty.)\n\nyt_image_url is not accepted; YouTube takes yt_video_url only. (Images sent for YouTube.)\n\n<prefix>_image_url and <prefix>_video_url cannot be combined; only Instagram and Threads take images and a video together. (Images and a video for one network other than Instagram or Threads.)\n\n<prefix>_image_url takes at most <n> images for <network>. (More images than that network allows. Instagram and Threads count images and video together and answer \"_image_url and _video_url take at most  media items together for .\")\n\n<prefix>_media_order may only hold the URLs given in <prefix>_image_url and <prefix>_video_url. (A per-network order names a URL outside that network's own media.)\n\n<prefix>_alt_text entries may have at most 1000 characters. (A per-network alt text entry is longer than 1000 characters.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library or the content does not belong to the workspace owner.)\n\nYou are not allowed to upload video file in your current plan. Please upgrade your RecurPost plan. (video_url sent while the workspace owner is on a free plan.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not one of your workspaces or your membership is not active.)\n\nThis library is not part of the selected workspace. (The library is the owner's but not in the named workspace_id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Media URL is not allowed: <url>. Please supply a publicly reachable http or https URL. (An image_url, video_url, thumbnail, ln_document or thread media URL is not http/https or its host resolves to a private, loopback or reserved address.)\n\nInvalid url parameter supplied (url (or the first link in the text) is not a valid public URL.)\n\nURL is not a video (detected content type: <type>). Please supply a valid video URL. (video_url answers a non-video content type.)\n\nInvalid video format (detected: <type>). Supported formats: mp4, mov (video_url is neither mp4 nor mov by extension or content type.)\n\nThe media URL could not be downloaded. (video_url or ln_document could not be read.)\n\nFailed to upload video. The URL was reachable but the file could not be processed. (The downloaded video was refused by storage (size over 2 GB, unreadable file).)\n\nURL is not an image (detected content type: <type>). Please supply a valid image URL. (An image_url answers a non-image content type.)\n\nInvalid image url parameter supplied. The URL did not return a recognizable image. (An image_url could not be read as an image.)\n\nFailed to upload image. The URL was reachable but the file could not be processed. (The image could not be stored.)\n\nInvalid <param> parameter supplied. The URL did not return a recognizable image. (fb_thumb, in_thumb, ln_thumb or yt_thumb is not an image (only checked on video posts with hosting on).)\n\nFailed to upload <param>. The URL was reachable but the file could not be processed. (A thumbnail could not be stored.)\n\nThe uploaded file at <url> is missing or is not a <image|video> (detected <type>). (A media_upload_url URL was never PUT to, or was PUT with the wrong Content-Type.)\n\nFiles are limited to 2 GB. (A media_upload_url object is larger than 2 GB.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Content validation failed! (The app's content validator refused one or more network tabs (text too long, media that the network does not accept, a reel without video, ...). The body carries `error_details`, an object keyed by network with the reason.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_content_search": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Find active library posts whose text, link title, variation or network version contains a phrase.",
                "description": "Searches the active posts of one library, or of every library in the workspace when `library_id` is left out. A post matches when its text, its link title, one of its message variations or one of its per-network messages contains `search_text` (case-insensitive substring). Draft posts are not searched.\nEach result is a `/api/library_content_list` item plus the library it sits in. No match answers 200 with an empty `content` list.\n\ncreated_at on search results: Search rows do not carry the creation time, so `created_at` is blank on this endpoint.",
                "operationId": "library_content_search",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "search_text": {
                                        "type": "string",
                                        "description": "Phrase to look for. Leading and trailing spaces are trimmed; blank is a 400.",
                                        "example": "repurpose"
                                    },
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted library id to search in. Omit to search every library of the workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Page number, from 1.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "per_page": {
                                        "type": "integer",
                                        "description": "Results per page, 1 to 50. Larger values are capped at 50.",
                                        "default": "20",
                                        "example": 20
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "search_text"
                                ],
                                "example": {
                                    "search_text": "repurpose"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "total": {
                                            "type": "integer",
                                            "description": "Matching posts across all pages."
                                        },
                                        "page": {
                                            "type": "integer",
                                            "description": "The page returned."
                                        },
                                        "per_page": {
                                            "type": "integer",
                                            "description": "The page size applied, after the cap of 50."
                                        },
                                        "content": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "description": "A matching post with the `/api/library_content_list` item fields (`id`, `message`, `title`, `description`, `url`, `image_url`, `images`, `video_url`, `live_date`, `expire_date`, `variations`, `created_at`) plus `library`.",
                                                "properties": {
                                                    "library": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "description": "Encrypted id of the library the post sits in."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Name of that library."
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "total": 1,
                                    "page": 1,
                                    "per_page": 20,
                                    "content": [
                                        {
                                            "id": "pQ8sL3vY2a==",
                                            "message": "Five ways to repurpose your best blog post",
                                            "title": "Repurposing guide",
                                            "description": "Turn one article into a week of social posts.",
                                            "url": "https://example.com/repurposing-guide",
                                            "image_url": "https://cdn.example.com/media/guide.jpg",
                                            "images": [
                                                "https://cdn.example.com/media/guide.jpg"
                                            ],
                                            "video_url": "",
                                            "live_date": "",
                                            "expire_date": "2026-12-31",
                                            "variations": 2,
                                            "created_at": "",
                                            "library": {
                                                "id": "nX2k9Qp7Lw==",
                                                "name": "Evergreen"
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "search_text is required. (search_text is missing or blank.)\n\nlibrary_id is invalid. (library_id was sent and does not decrypt to a library id.)\n\nThe search could not be run. (The app refused the search without a message.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (library_id does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "This library is not part of the selected workspace. (workspace_id and library_id were both sent and the library sits in another workspace.)\n\nWorkspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_content_move": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Move posts out of one library into one or more other libraries.",
                "description": "Moves each post in `content_ids` from `from_library_id` into every library in `to_library_ids`. Posts are handled one at a time, so a refused post is reported in `failed` with its own status and the others still move. The call is an error only when no post moved; the answer is then the first failure's status and message.\nThe post gets a new id in every destination. The id you sent stops being valid after the move; read the new ones from `moved[].new_ids`.\n\nIds change: Moving creates a fresh post in each destination and removes the original, so every reference you hold to the old id (variations, queue lookups, your own database) must be updated from `new_ids`. With several destinations the order of `new_ids` is not guaranteed to follow `to_library_ids`; read each new post to see which library it is in.\n\nActive posts only: Drafts cannot be moved with this endpoint.",
                "operationId": "library_content_move",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "content_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted post ids to move: one id, a comma-separated string or an array, at most 50. `id` is accepted as an alias. All ids must decrypt or the whole list is treated as empty.",
                                        "example": [
                                            "pQ8sL3vY2a==",
                                            "rM1kD7fB9z=="
                                        ]
                                    },
                                    "from_library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library the posts sit in now. A post that is not in this library is reported in `failed` with status 404.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "to_library_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted ids of the destination libraries: one id, a comma-separated string or an array, at most 50.",
                                        "example": [
                                            "bT4r8Vz1Kc=="
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "content_ids",
                                    "from_library_id",
                                    "to_library_ids"
                                ],
                                "example": {
                                    "content_ids": [
                                        "pQ8sL3vY2a==",
                                        "rM1kD7fB9z=="
                                    ],
                                    "from_library_id": "nX2k9Qp7Lw==",
                                    "to_library_ids": [
                                        "bT4r8Vz1Kc=="
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 when at least one post moved."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`N post(s) moved.`"
                                        },
                                        "moved": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "The post id you sent. It no longer resolves after the move."
                                                    },
                                                    "new_ids": {
                                                        "type": "array",
                                                        "items": [],
                                                        "description": "Encrypted ids the post now has, one per destination library."
                                                    }
                                                }
                                            }
                                        },
                                        "failed": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "A post that did not move."
                                                    },
                                                    "status": {
                                                        "type": "integer",
                                                        "description": "Why: 404 not in the source library, 409 one-time-use conflict, 403 plan limit, 400 other refusal."
                                                    },
                                                    "error": {
                                                        "type": "string",
                                                        "description": "The reason as text."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "1 post(s) moved.",
                                    "moved": [
                                        {
                                            "id": "pQ8sL3vY2a==",
                                            "new_ids": [
                                                "zK5wN2hT8e=="
                                            ]
                                        }
                                    ],
                                    "failed": [
                                        {
                                            "id": "rM1kD7fB9z==",
                                            "status": 404,
                                            "error": "The post is not in the source library."
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "content_ids, from_library_id and to_library_ids are required. (One of the three is missing or does not decrypt.)\n\nAt most 50 ids per call; N were sent. (content_ids or to_library_ids holds more than 50 ids.)\n\nThe post could not be transferred. (No post moved and the app refused the first one without a message.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The source library, a destination library or a post does not belong to the workspace owner.)\n\nYou have maximum allowed number of posts in your library. Please upgrade your plan or delete few posts to add new ones. (No post moved and the first one hit the plan's post limit (wording of the upgrade text varies by plan).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "This library is not part of the selected workspace. (workspace_id was sent and one of the libraries sits in another workspace.)\n\nWorkspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThe post is not in the source library. (No post moved and the first one was not in from_library_id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "A post with message variations can not be moved to one-time-use library. (No post moved and the first one has variations while a destination is one-time-use.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_content_copy": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Copy posts from one library into one or more other libraries.",
                "description": "Copies each post in `content_ids` from `from_library_id` into every library in `to_library_ids`. The original stays where it is. Posts are handled one at a time, so a refused post is reported in `failed` with its own status and the others are still copied. The call is an error only when no post was copied; the answer is then the first failure's status and message.\nEach copy is a new post with its own id, returned in `copied[].new_ids`, one per destination. Editing the copy does not change the original.\n\nCopies count against your plan: Every copy is a new post and counts toward the plan's post limit. With several destinations the order of `new_ids` is not guaranteed to follow `to_library_ids`; read each new post to see which library it is in. Drafts cannot be copied with this endpoint.",
                "operationId": "library_content_copy",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "content_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted post ids to copy: one id, a comma-separated string or an array, at most 50. `id` is accepted as an alias. All ids must decrypt or the whole list is treated as empty.",
                                        "example": [
                                            "pQ8sL3vY2a=="
                                        ]
                                    },
                                    "from_library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library the posts sit in. A post that is not in this library is reported in `failed` with status 404.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "to_library_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted ids of the destination libraries: one id, a comma-separated string or an array, at most 50.",
                                        "example": [
                                            "bT4r8Vz1Kc==",
                                            "hJ6cR0qW4p=="
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "content_ids",
                                    "from_library_id",
                                    "to_library_ids"
                                ],
                                "example": {
                                    "content_ids": [
                                        "pQ8sL3vY2a=="
                                    ],
                                    "from_library_id": "nX2k9Qp7Lw==",
                                    "to_library_ids": [
                                        "bT4r8Vz1Kc==",
                                        "hJ6cR0qW4p=="
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 when at least one post was copied."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`N post(s) copied.`"
                                        },
                                        "copied": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "The source post id you sent; it stays valid."
                                                    },
                                                    "new_ids": {
                                                        "type": "array",
                                                        "items": [],
                                                        "description": "Encrypted ids of the copies, one per destination library."
                                                    }
                                                }
                                            }
                                        },
                                        "failed": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "A post that was not copied."
                                                    },
                                                    "status": {
                                                        "type": "integer",
                                                        "description": "Why: 404 not in the source library, 409 one-time-use conflict, 403 plan limit, 400 other refusal."
                                                    },
                                                    "error": {
                                                        "type": "string",
                                                        "description": "The reason as text."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "1 post(s) copied.",
                                    "copied": [
                                        {
                                            "id": "pQ8sL3vY2a==",
                                            "new_ids": [
                                                "zK5wN2hT8e==",
                                                "aF3gU9xC1d=="
                                            ]
                                        }
                                    ],
                                    "failed": []
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "content_ids, from_library_id and to_library_ids are required. (One of the three is missing or does not decrypt.)\n\nAt most 50 ids per call; N were sent. (content_ids or to_library_ids holds more than 50 ids.)\n\nThe post could not be transferred. (No post was copied and the app refused the first one without a message.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The source library, a destination library or a post does not belong to the workspace owner.)\n\nYou have maximum allowed number of posts in your library. Please upgrade your plan or delete few posts to add new ones. (No post was copied and the first one hit the plan's post limit (wording of the upgrade text varies by plan).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "This library is not part of the selected workspace. (workspace_id was sent and one of the libraries sits in another workspace.)\n\nWorkspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThe post is not in the source library. (No post was copied and the first one was not in from_library_id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "A post with message variations can not be copied to one-time-use library. (No post was copied and the first one has variations while a destination is one-time-use.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_content_delete": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Delete one or more posts from a library.",
                "description": "Deletes the posts in `id` from the library `library_id`. Every id is checked first: all must be the workspace owner's and all must sit in that library, otherwise nothing is deleted. The deletion is permanent; the post, its per-network versions and its variations are removed.\n\nNo undo: Deleted posts cannot be restored through the API. Duplicate ids in the list are counted once.",
                "operationId": "library_content_delete",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library the posts sit in.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "id": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted post ids to delete: one id, a comma-separated string or an array, at most 50. All ids must decrypt or the whole list is treated as empty.",
                                        "example": [
                                            "pQ8sL3vY2a==",
                                            "rM1kD7fB9z=="
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "library_id",
                                    "id"
                                ],
                                "example": {
                                    "library_id": "nX2k9Qp7Lw==",
                                    "id": [
                                        "pQ8sL3vY2a==",
                                        "rM1kD7fB9z=="
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Content deleted successfully`."
                                        },
                                        "deleted_count": {
                                            "type": "integer",
                                            "description": "Number of distinct post ids deleted."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Content deleted successfully",
                                    "deleted_count": 2
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (library_id or id is missing or does not decrypt.)\n\nAt most 50 ids per call; N were sent. (id holds more than 50 ids.)\n\nYou have insufficient permissions to perform this action... (You are not a member of the library's workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library or one of the posts does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "This library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\nWorkspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nPost <id> is not in this library. (One of the posts sits in another library; the message names the encrypted id. Nothing is deleted.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/content_variation_list": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "List the message variations of a library post.",
                "description": "Returns the message variations of one post. Variations are alternative texts RecurPost rotates through each time the post comes up, so the same post does not repeat word for word. Variations not yet used in the current rotation come first, then the ones already published. A post without variations answers 200 with an empty list.",
                "operationId": "content_variation_list",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library the post sits in.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "content_id": {
                                        "type": "string",
                                        "description": "Encrypted post id.",
                                        "example": "pQ8sL3vY2a=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "library_id",
                                    "content_id"
                                ],
                                "example": {
                                    "library_id": "nX2k9Qp7Lw==",
                                    "content_id": "pQ8sL3vY2a=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "variations": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted variation id for `/api/content_variation_update` and `/api/content_variation_delete`."
                                                    },
                                                    "text": {
                                                        "type": "string",
                                                        "description": "The variation text."
                                                    },
                                                    "published": {
                                                        "type": "boolean",
                                                        "description": "True once the variation has gone out in the current rotation."
                                                    },
                                                    "priority": {
                                                        "type": "integer",
                                                        "description": "Position of the variation in the rotation."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "variations": [
                                        {
                                            "id": "vC2nH8kQ5s==",
                                            "text": "Repurpose your best post five different ways",
                                            "published": false,
                                            "priority": 2
                                        },
                                        {
                                            "id": "vD9pJ1mR3t==",
                                            "text": "One blog post, five social posts: here is how",
                                            "published": true,
                                            "priority": 1
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "library_id and content_id are required. (Either id is missing or does not decrypt.)\n\nSorry, something went wrong. Please try again later. (You are not a member of the library's workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library or the post does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "This library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\nWorkspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nNo post found. (The post is not in the given library.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The variations could not be read. (The app returned nothing usable.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/content_variation_add": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Add a message variation to a library post.",
                "description": "Adds a new text variation to the post and returns the full variation list, as `/api/content_variation_list` does. The text must differ from the post's text and from its other variations. A variation counts as a post toward the plan's post limit.",
                "operationId": "content_variation_add",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library the post sits in.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "content_id": {
                                        "type": "string",
                                        "description": "Encrypted post id.",
                                        "example": "pQ8sL3vY2a=="
                                    },
                                    "text": {
                                        "type": "string",
                                        "description": "The variation text. Leading and trailing spaces are trimmed; blank is a 400.",
                                        "example": "Repurpose your best post five different ways"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "library_id",
                                    "content_id",
                                    "text"
                                ],
                                "example": {
                                    "library_id": "nX2k9Qp7Lw==",
                                    "content_id": "pQ8sL3vY2a==",
                                    "text": "Repurpose your best post five different ways"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Variation added.`"
                                        },
                                        "variations": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "description": "Every variation of the post after the add, with `id`, `text`, `published` and `priority` as on `/api/content_variation_list`. The new one is the entry whose `text` you sent."
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Variation added.",
                                    "variations": [
                                        {
                                            "id": "vC2nH8kQ5s==",
                                            "text": "Repurpose your best post five different ways",
                                            "published": false,
                                            "priority": 2
                                        },
                                        {
                                            "id": "vD9pJ1mR3t==",
                                            "text": "One blog post, five social posts: here is how",
                                            "published": true,
                                            "priority": 1
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "library_id and content_id are required. (Either id is missing or does not decrypt.)\n\ntext is required. (text is missing or blank.)\n\nSorry, something went wrong. Please try again later. (You are not a member of the library's workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library or the post does not belong to the workspace owner.)\n\nYou have maximum allowed number of posts in your library. Please upgrade your plan or delete few posts to add new ones. (The plan's post limit is reached (wording of the upgrade text varies by plan).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "This library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\nWorkspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nNo post found. (The post is not in the given library.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This variation already exists, please change it and try again. (text equals the post's text or an existing variation.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The variations could not be read. (The app returned nothing usable.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/content_variation_update": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Change the text of a message variation.",
                "description": "Replaces the text of one variation and returns the full variation list, as `/api/content_variation_list` does. The new text must differ from the post's text and from the other variations.",
                "operationId": "content_variation_update",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library the post sits in.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "content_id": {
                                        "type": "string",
                                        "description": "Encrypted post id.",
                                        "example": "pQ8sL3vY2a=="
                                    },
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted variation id from `/api/content_variation_list`. Must belong to `content_id`.",
                                        "example": "vC2nH8kQ5s=="
                                    },
                                    "text": {
                                        "type": "string",
                                        "description": "The new variation text. Leading and trailing spaces are trimmed; blank is a 400.",
                                        "example": "Repurpose your best post in five ways"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "library_id",
                                    "content_id",
                                    "id",
                                    "text"
                                ],
                                "example": {
                                    "library_id": "nX2k9Qp7Lw==",
                                    "content_id": "pQ8sL3vY2a==",
                                    "id": "vC2nH8kQ5s==",
                                    "text": "Repurpose your best post in five ways"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Variation updated.`"
                                        },
                                        "variations": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "description": "Every variation of the post after the change, with `id`, `text`, `published` and `priority` as on `/api/content_variation_list`."
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Variation updated.",
                                    "variations": [
                                        {
                                            "id": "vC2nH8kQ5s==",
                                            "text": "Repurpose your best post in five ways",
                                            "published": false,
                                            "priority": 2
                                        },
                                        {
                                            "id": "vD9pJ1mR3t==",
                                            "text": "One blog post, five social posts: here is how",
                                            "published": true,
                                            "priority": 1
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "library_id and content_id are required, with the variation id. (library_id, content_id or id is missing or does not decrypt.)\n\ntext is required. (text is missing or blank.)\n\nSorry, something went wrong. Please try again later. (You are not a member of the library's workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library or the post does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "This library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\nWorkspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nVariation not found on this post. (id is not a variation of content_id.)\n\nNo post found. (The post is not in the given library.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This variation already exists, please change it and try again. (text equals the post's text or another variation.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The variations could not be read. (The app returned nothing usable.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/content_variation_delete": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Delete a message variation from a library post.",
                "description": "Removes one variation and returns the variations that remain, as `/api/content_variation_list` does. Deleting the last variation answers 200 with an empty list.",
                "operationId": "content_variation_delete",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library the post sits in.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "content_id": {
                                        "type": "string",
                                        "description": "Encrypted post id.",
                                        "example": "pQ8sL3vY2a=="
                                    },
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted variation id from `/api/content_variation_list`. Must belong to `content_id`.",
                                        "example": "vC2nH8kQ5s=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "library_id",
                                    "content_id",
                                    "id"
                                ],
                                "example": {
                                    "library_id": "nX2k9Qp7Lw==",
                                    "content_id": "pQ8sL3vY2a==",
                                    "id": "vC2nH8kQ5s=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Variation deleted.`"
                                        },
                                        "variations": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "description": "The variations left on the post, with `id`, `text`, `published` and `priority` as on `/api/content_variation_list`. Empty when none remain."
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Variation deleted.",
                                    "variations": [
                                        {
                                            "id": "vD9pJ1mR3t==",
                                            "text": "One blog post, five social posts: here is how",
                                            "published": true,
                                            "priority": 1
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "library_id and content_id are required, with the variation id. (library_id, content_id or id is missing or does not decrypt.)\n\nSorry, something went wrong. Please try again later. (You are not a member of the library's workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library or the post does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "This library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\nWorkspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nVariation not found on this post. (id is not a variation of content_id.)\n\nNo post found. (The post is not in the given library.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The variations could not be read. (The app returned nothing usable.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_content_order": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Move a post to a position in a library's publishing order, or shuffle the whole order.",
                "description": "Changes the order in which a library's posts go out. `action` `move` puts `content_id` at `position` (1 publishes next) and shifts the posts in between; `shuffle` randomises the whole library. Both answer with the complete new order, one row per post with its position and encrypted id. Each account's place in that order is read and changed with `/api/library_pointers`.\nMoving a post to the position it already has changes nothing and still answers 200 with the order.\n\nOrder versus pointers: The order is the library's. Every account connected to the library has its own pointer into it (`/api/library_pointers`), so moving a post to position 1 makes it the next post for accounts whose pointer is at the start; an account further down the order reaches it on its next cycle.",
                "operationId": "library_content_order",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted library id.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "`move` places one post, `shuffle` randomises the order.",
                                        "enum": [
                                            "move",
                                            "shuffle"
                                        ],
                                        "default": "move",
                                        "example": "move"
                                    },
                                    "content_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the post to move. Required when action is `move`; the post must be in the library.",
                                        "example": "pQ8sL3vY2a=="
                                    },
                                    "position": {
                                        "type": "integer",
                                        "description": "New position, 1 to the number of posts in the library (1 publishes next). Required when action is `move`.",
                                        "example": 1
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": "nX2k9Qp7Lw=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Post moved to position N.` or `Library order shuffled.`"
                                        },
                                        "order": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "position": {
                                                        "type": "integer",
                                                        "description": "Position in the publishing order, 1 first."
                                                    },
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted id of the post at that position."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Post moved to position 1.",
                                    "order": [
                                        {
                                            "position": 1,
                                            "id": "pQ8sL3vY2a=="
                                        },
                                        {
                                            "position": 2,
                                            "id": "zK5wN2hT8e=="
                                        },
                                        {
                                            "position": 3,
                                            "id": "aF3gU9xC1d=="
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Send the library id and action as move or shuffle. (id is missing or does not decrypt, or action is another word.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nposition must be between 1 and N. (action move with a position outside the library's size (N is the number of posts).)\n\nSorry, something went wrong. Please try again later. (The app could not shuffle the library.)\n\nThe order could not be changed. (The app refused the change without a message; a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\ncontent_id is not a post of this library. (action move with a content_id that is missing, does not decrypt or is not in this library.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_delete": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Delete a library with its posts, drafts, schedules and feeds.",
                "description": "Deletes library `id` for good, together with the posts and drafts in it, the schedules attached to it and the RSS feeds that fill it. The call needs `confirm=true`.\nPosts the library already placed in the queue are not touched: they stay queued and publish at their time, as when the library is deleted in the app. `queued_posts_kept` in the answer says so.\n\nNot reversible: The library, its posts, their media, the drafts, the schedules attached to the library and its feeds are removed. Copy what you need with `/api/library_content_copy` or `/api/library_duplicate` first.",
                "operationId": "library_delete",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted library id.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be `true`; without it the call answers 400 and deletes nothing.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "id",
                                    "confirm"
                                ],
                                "example": {
                                    "id": "nX2k9Qp7Lw==",
                                    "confirm": true
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Library deleted.`"
                                        },
                                        "queued_posts_kept": {
                                            "type": "boolean",
                                            "description": "Always `true`: items the library already queued stay in the queue."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Library deleted.",
                                    "queued_posts_kept": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or does not decrypt to a library id.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nSend confirm=true to delete the library with its posts, drafts, schedules and feeds. (confirm is missing or not true.)\n\nThe library could not be deleted. (The app refused without a message; a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library does not belong to the workspace owner.)\n\nYou have no permission to delete library... (You are not a member of the library's workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_duplicate": {
            "post": {
                "tags": [
                    "Libraries"
                ],
                "summary": "Copy a library with its posts, variations, drafts and season into a new library.",
                "description": "Creates a new library named `<name>-copy` holding copies of every post of library `id`, with their message variations, the drafts and the seasonal window. The answer is the new library in the shape of `/api/library_details`; its posts have new ids of their own.\nEvery copied post counts toward the plan's library post limit, so a plan without room for the whole library refuses the copy.\n\nWhat is not copied: The copy is a fresh library: it has no schedules, no feeds, no share link and no account pointers. Attach schedules to it as you would to a new library.",
                "operationId": "library_duplicate",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library to copy.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": "nX2k9Qp7Lw=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Library duplicated.`"
                                        },
                                        "library": {
                                            "type": "object",
                                            "description": "The new library, same fields as `/api/library_details`: `id`, `name`, `color`, `status`, `one_time_use`, `seasonal`, `counts`, `created_at`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Library duplicated.",
                                    "library": {
                                        "id": "bT4r8Vz1Kc==",
                                        "name": "Evergreen 2026-copy",
                                        "color": "#abcdef",
                                        "status": "active",
                                        "one_time_use": false,
                                        "seasonal": null,
                                        "counts": {
                                            "posts": 5,
                                            "drafts": 1,
                                            "variations": 2,
                                            "unpublished_posts": 5
                                        },
                                        "created_at": "2026-10-23 09:00:00"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or does not decrypt to a library id.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nThe library could not be duplicated. (The app answered without the new library's id; a 500 when it sent no status.)\n\nLibrary not found. (The copy was made but could not be read back.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library does not belong to the workspace owner.)\n\nYou have no permission to create duplicate library. (You are not a member of the library's workspace.)\n\nIn order to duplicate this library you need to either upgrade your plan or delete some updates from this library. (The owner's library post limit has no room for the copies (the upgrade wording varies by plan).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/expired_content": {
            "post": {
                "tags": [
                    "Library Tools"
                ],
                "summary": "List posts that left their library, restore one as a copy, delete one for good, or expire a live post.",
                "description": "Expired content is the holding area for posts that are no longer in a library: posts a one-time-use library published and dropped, posts whose expire date passed, and posts you expire by hand. `action` picks the operation:\n- `list` (default): the expired posts of the workspace, paged, each with the library it came from.\n- `expire`: takes a live post or draft (`content_id`) out of its library and into expired content.\n- `restore`: copies an expired post (`content_id`) into one or more libraries (`library_ids`). The expired original stays; the copies are new posts whose ids come back in `new_ids`.\n- `delete`: removes an expired post and its media for good; needs `confirm=true`.\n\nRestore makes copies: The expired post stays in expired content after a restore; each library in `library_ids` gets a new post with its own id, and every copy counts toward the plan's library post limit. Delete the expired original with `action=delete` once you no longer need it.",
                "operationId": "expired_content",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "What to do; see above.",
                                        "enum": [
                                            "list",
                                            "restore",
                                            "delete",
                                            "expire"
                                        ],
                                        "default": "list",
                                        "example": "list"
                                    },
                                    "content_id": {
                                        "type": "string",
                                        "description": "Encrypted post id. Required when action is `restore`, `delete` or `expire`. For restore and delete it must be an expired post (from the list); for expire a post that is not expired yet.",
                                        "example": "pQ8sL3vY2a=="
                                    },
                                    "library_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted ids of the libraries to copy the post into: one id, a comma-separated string or an array, at most 50. Required when action is `restore`.",
                                        "example": [
                                            "nX2k9Qp7Lw=="
                                        ]
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be `true` when action is `delete`.",
                                        "example": true
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Page of the list, from 1. Read when action is `list`.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "per_page": {
                                        "type": "integer",
                                        "description": "Posts per page, 1 to 50. Read when action is `list`.",
                                        "default": "20",
                                        "example": 20
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success` for list; `Post expired; it left its library and shows under expired content.`; `Post restored as a copy in N library(ies); the expired original stays.`; `Expired post deleted.`"
                                        },
                                        "page": {
                                            "type": "integer",
                                            "description": "list: the page returned."
                                        },
                                        "per_page": {
                                            "type": "integer",
                                            "description": "list: posts per page."
                                        },
                                        "items": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "list: encrypted id of the expired post."
                                                    },
                                                    "message": {
                                                        "type": "string",
                                                        "description": "list: post text."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "list: link title, blank without a link."
                                                    },
                                                    "description": {
                                                        "type": "string",
                                                        "description": "list: link description."
                                                    },
                                                    "url": {
                                                        "type": "string",
                                                        "description": "list: the link, blank when none."
                                                    },
                                                    "image_url": {
                                                        "type": "string",
                                                        "description": "list: first image, link preview image or video cover."
                                                    },
                                                    "images": {
                                                        "type": "array",
                                                        "items": [],
                                                        "description": "list: every image URL."
                                                    },
                                                    "video_url": {
                                                        "type": "string",
                                                        "description": "list: the video, blank when none."
                                                    },
                                                    "live_date": {
                                                        "type": "string",
                                                        "description": "list: `YYYY-MM-DD` the post went live, blank when none."
                                                    },
                                                    "expire_date": {
                                                        "type": "string",
                                                        "description": "list: `YYYY-MM-DD` the post expired, blank when none."
                                                    },
                                                    "variations": {
                                                        "type": "integer",
                                                        "description": "list: number of message variations, 1 without any."
                                                    },
                                                    "created_at": {
                                                        "type": "string",
                                                        "description": "list: when the post was created."
                                                    },
                                                    "origin_library": {
                                                        "type": "object",
                                                        "description": "list: `id` and `name` of the library the post came from, or `null` when it is gone."
                                                    }
                                                }
                                            }
                                        },
                                        "new_ids": {
                                            "type": "array",
                                            "items": [],
                                            "description": "restore: encrypted ids of the copies, one per destination library."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "page": 1,
                                    "per_page": 20,
                                    "items": [
                                        {
                                            "id": "pQ8sL3vY2a==",
                                            "message": "Our summer sale ends tonight.",
                                            "title": "",
                                            "description": "",
                                            "url": "",
                                            "image_url": "https://cdn.example.com/u/1/sale.jpg",
                                            "images": [
                                                "https://cdn.example.com/u/1/sale.jpg"
                                            ],
                                            "video_url": "",
                                            "live_date": "",
                                            "expire_date": "2026-08-31",
                                            "variations": 1,
                                            "created_at": "2026-06-01 09:00:00",
                                            "origin_library": {
                                                "id": "nX2k9Qp7Lw==",
                                                "name": "Summer 2026"
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "action must be list, restore, delete or expire. (action is another word.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\ncontent_id is required. (restore, delete or expire without a content_id that decrypts.)\n\nNo post found. (expire on a post the app could not find.)\n\nThe post could not be expired. (expire refused by the app without a message; a 500 when it sent no status.)\n\nSend confirm=true to delete the expired post and its media for good. (delete without confirm=true.)\n\nThe post could not be deleted. (delete refused by the app without a message; a 500 when it sent no status.)\n\nlibrary_ids is required. (restore without library_ids, or one of them does not decrypt (the whole list is then treated as empty).)\n\nAt most 50 ids per call; N were sent. (library_ids holds more than 50 ids.)\n\nThe post could not be restored. (restore refused by the app without a message; a 500 when it sent no status.)\n\nThe expired posts could not be read. (list failed in the app; its own message replaces this one when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The post, or one of the libraries in library_ids, does not belong to the workspace owner.)\n\nYou have maximum allowed number of posts in your library. Please upgrade your plan or delete few posts to add new ones. (restore would pass the owner's library post limit (the upgrade wording varies by plan).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and a library in library_ids sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This post is already expired. (expire on a post that is in expired content.)\n\nThis post is not expired. (restore or delete on a post that is still in a library.)\n\nA post with message variations can not be copied to one-time-use library. (restore of a post with variations into a one-time-use library.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_drafts": {
            "post": {
                "tags": [
                    "Library Tools"
                ],
                "summary": "List, read, edit, publish or delete the drafts of a library.",
                "description": "A draft is a library post with a live date in the future: it sits in the library but is not scheduled until that day. `action` picks the operation on library `library_id`:\n- `list` (default): the drafts of the library, 20 a page.\n- `get`: one draft (`content_id`) with its live and expire dates.\n- `update`: changes the fields you send over the draft's current values; a field left out keeps its value. The draft must keep a live date.\n- `publish`: clears the live date so the post joins the library now; the other fields you send are applied at the same time.\n- `delete`: removes the draft and its media; needs `confirm=true`.\n\nThe content fields here are the simple ones of a library post (one message, one link, one image, one video); per-network tabs are not touched. For a full rewrite use `/api/library_content_update`.\n\nPatch semantics, unlike library_content_update: update and publish merge your fields over the draft's current values, so you can change one field alone. `/api/library_content_update` is a full replacement; use it to rewrite per-network tabs.\n\ngmb_cta_type 1 is treated as none: The app stores Learn more as code 1, but this endpoint keeps only codes above 1; sending 1 clears the button. Set a Learn more button through `/api/library_content_update` with `gbp_cta` instead.",
                "operationId": "library_drafts",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted library id.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "What to do; see above.",
                                        "enum": [
                                            "list",
                                            "get",
                                            "update",
                                            "publish",
                                            "delete"
                                        ],
                                        "default": "list",
                                        "example": "list"
                                    },
                                    "content_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the draft. Required for every action but `list`; it must be a draft of this library.",
                                        "example": "pQ8sL3vY2a=="
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Page of the list, from 1; 20 drafts a page. Read when action is `list`.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "New post text. update and publish only.",
                                        "example": "Three ways to plan a month of posts"
                                    },
                                    "title": {
                                        "type": "string",
                                        "description": "Link title. update and publish only.",
                                        "example": "Plan a month of posts"
                                    },
                                    "description": {
                                        "type": "string",
                                        "description": "Link description. update and publish only.",
                                        "example": "A short guide to batching your content."
                                    },
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public http or https link. Send blank to remove it. update and publish only.",
                                        "example": "https://example.com/plan"
                                    },
                                    "image_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public http or https image URL, one image. Send blank to remove it. update and publish only.",
                                        "example": "https://example.com/img/plan.jpg"
                                    },
                                    "video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public http or https video URL. Send blank to remove it. update and publish only.",
                                        "example": "https://example.com/video/plan.mp4"
                                    },
                                    "live_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "`YYYY-MM-DD` the draft goes live. update must leave the draft with a live date; publish clears it whatever you send.",
                                        "example": "2026-12-01"
                                    },
                                    "expire_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "`YYYY-MM-DD` the post stops recurring; blank clears it. update and publish only.",
                                        "example": "2027-01-31"
                                    },
                                    "gmb_cta_type": {
                                        "type": "integer",
                                        "description": "Google Business call-to-action code as the app stores it: 2 Sign up, 3 Buy, 4 Order online, 5 Book, 6 Call now, 8 Offer. 0 or 1 clears the button. update and publish only.",
                                        "example": 2
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be `true` when action is `delete`.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "library_id"
                                ],
                                "example": {
                                    "library_id": "nX2k9Qp7Lw=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success` for list and get; `Draft updated.`; `Draft published to the library.`; `Draft deleted.`"
                                        },
                                        "page": {
                                            "type": "integer",
                                            "description": "list: the page returned."
                                        },
                                        "per_page": {
                                            "type": "integer",
                                            "description": "list: always 20."
                                        },
                                        "items": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "description": "list: one draft per item with `id`, `message`, `title`, `description`, `url`, `image_url`, `images`, `video_url`, `live_date`, `expire_date`, `variations`, `created_at` (as `/api/library_content_list` shows a post) plus `comments`, the number of client comments on it."
                                            }
                                        },
                                        "draft": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "get, update, publish: encrypted id of the draft."
                                                },
                                                "message": {
                                                    "type": "string",
                                                    "description": "Post text."
                                                },
                                                "title": {
                                                    "type": "string",
                                                    "description": "Link title."
                                                },
                                                "description": {
                                                    "type": "string",
                                                    "description": "Link description."
                                                },
                                                "url": {
                                                    "type": "string",
                                                    "description": "The link, blank when none."
                                                },
                                                "image_url": {
                                                    "type": "string",
                                                    "description": "The image, blank when none."
                                                },
                                                "video_url": {
                                                    "type": "string",
                                                    "description": "The video, blank when none."
                                                },
                                                "live_date": {
                                                    "type": "string",
                                                    "description": "`YYYY-MM-DD`; blank after publish."
                                                },
                                                "expire_date": {
                                                    "type": "string",
                                                    "description": "`YYYY-MM-DD` or blank."
                                                },
                                                "gmb_cta_type": {
                                                    "type": "integer",
                                                    "description": "Google Business call-to-action code, 0 when none."
                                                },
                                                "variations": {
                                                    "type": "integer",
                                                    "description": "Number of message variations, 1 without any."
                                                },
                                                "created_at": {
                                                    "type": "string",
                                                    "description": "When the draft was created."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Draft updated.",
                                    "draft": {
                                        "id": "pQ8sL3vY2a==",
                                        "message": "Three ways to plan a month of posts",
                                        "title": "",
                                        "description": "",
                                        "url": "",
                                        "image_url": "https://cdn.example.com/u/1/plan.jpg",
                                        "video_url": "",
                                        "live_date": "2026-12-01",
                                        "expire_date": "2027-01-31",
                                        "gmb_cta_type": 0,
                                        "variations": 1,
                                        "created_at": "2026-10-20 14:05:00"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Send library_id and action as list, get, update, publish or delete. (library_id is missing or does not decrypt, or action is another word.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\ncontent_id is required. (get, update, publish or delete without a content_id that decrypts.)\n\nSend confirm=true to delete the draft and its media. (delete without confirm=true.)\n\nDraft not found. (get, update or publish: the app could not read the draft; its own message (for example Sorry, something went wrong. Please try again later.) replaces this one when it sent one.)\n\nlive_date must be YYYY-MM-DD. (live_date (or expire_date, named in the message) is sent with a value in another format or not a real date.)\n\nurl must be a public http or https address. (url, image_url or video_url (named in the message) is sent with a value that is not a public http(s) URL.)\n\nvideo_url must point to a video file. (video_url ends in gif, jpg, jpeg or png.)\n\nThe draft needs a message, a link, an image or a video. (update or publish would leave the post empty.)\n\nThe draft could not be saved. (update or publish refused by the app without a message (its own text, for example There is no content in your post, please try again., replaces this one); a 500 when it sent no status.)\n\nYou have insufficient permissions to perform this action... (delete: you are not a member of the library's workspace.)\n\nThe draft could not be deleted. (delete refused by the app without a message; a 500 when it sent no status.)\n\nThe drafts could not be read. (list failed in the app; its own message replaces this one when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library or the draft does not belong to the workspace owner.)\n\nYou have maximum allowed number of posts in your library. Please upgrade your plan or delete few posts to add new ones. (publish would pass the owner's library post limit (the upgrade wording varies by plan).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\nThis post is not a draft of this library. (content_id is a live post, or a draft of another library.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This draft has no live date; send live_date to keep it a draft, or use publish. (update would leave the draft without a live date.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_bulk_edit": {
            "post": {
                "tags": [
                    "Library Tools"
                ],
                "summary": "Count a text across posts, replace it everywhere, or append a line to every post.",
                "description": "Find-and-replace over the posts of one library (`library_id`) or of the whole workspace (no `library_id`). `action` picks the operation:\n- `count` (default): how often `search_text` appears, split into post messages, X variations and per-network customised messages. Run it first; replace uses the same counting.\n- `replace`: rewrites every occurrence of `search_text` with `replace_text` (blank removes the text). Needs `confirm=true`. The answer carries the counts and how many places were rewritten.\n- `append`: adds `text` as a new last line to every post of the library or workspace, matching or not. Needs `confirm=true`.\n\n`include_variations` extends the operation to the X message variations of the posts and `include_customized` to the per-network versions; both are off by default, so only the main message is counted or changed.\n\nAppend touches every post: `append` is not filtered by `search_text`: the line is added to every post in scope, the whole workspace when no `library_id` is sent. Always send `library_id` unless you mean all libraries.\n\nReplaced count: `Replaced in N place(s).` adds up `counts.posts`, `counts.variations` and `counts.customized`, which is the number of messages touched. `counts.matches` can be higher when a message holds the text more than once.",
                "operationId": "library_bulk_edit",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "What to do; see above.",
                                        "enum": [
                                            "count",
                                            "replace",
                                            "append"
                                        ],
                                        "default": "count",
                                        "example": "count"
                                    },
                                    "search_text": {
                                        "type": "string",
                                        "description": "Text to look for, 1 to 500 characters. Required when action is `count` or `replace`.",
                                        "example": "#summer"
                                    },
                                    "replace_text": {
                                        "type": "string",
                                        "description": "Text that replaces each occurrence, at most 500 characters; blank or missing removes the text. Read when action is `replace`.",
                                        "example": "#autumn"
                                    },
                                    "text": {
                                        "type": "string",
                                        "description": "Line added at the end of every post, 1 to 500 characters. Required when action is `append`.",
                                        "example": "#evergreen"
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be `true` when action is `replace` or `append`.",
                                        "example": true
                                    },
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted library id to limit the operation to one library. Without it every post of the workspace is in scope.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "include_variations": {
                                        "type": "boolean",
                                        "description": "`true` also counts or changes the X message variations of the posts.",
                                        "default": "false",
                                        "example": false
                                    },
                                    "include_customized": {
                                        "type": "boolean",
                                        "description": "`true` also counts or changes the per-network customised messages.",
                                        "default": "false",
                                        "example": false
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success` for count; `Replaced in N place(s).` or `Nothing to replace.`; `Text appended to every post of the library.` or `Text appended to every post of the workspace.`"
                                        },
                                        "counts": {
                                            "type": "object",
                                            "properties": {
                                                "matches": {
                                                    "type": "integer",
                                                    "description": "count and replace: total occurrences of search_text."
                                                },
                                                "posts": {
                                                    "type": "integer",
                                                    "description": "count and replace: occurrences in post messages."
                                                },
                                                "variations": {
                                                    "type": "integer",
                                                    "description": "count and replace: occurrences in X message variations (0 unless include_variations)."
                                                },
                                                "customized": {
                                                    "type": "integer",
                                                    "description": "count and replace: occurrences in per-network messages (0 unless include_customized)."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Replaced in 5 place(s).",
                                    "counts": {
                                        "matches": 5,
                                        "posts": 3,
                                        "variations": 1,
                                        "customized": 1
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "action must be count, replace or append. (action is another word.)\n\nsearch_text is required. (count or replace without search_text.)\n\ntext is required. (append without text.)\n\nTexts are limited to 500 characters. (search_text, replace_text or text is longer than 500 characters.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nlibrary_id is invalid. (library_id is sent and does not decrypt.)\n\nSend confirm=true to rewrite every post of the library. (replace without confirm=true. The text reads append to for append, and of the workspace without a library_id.)\n\nThe posts could not be searched. (count or replace: the counting failed in the app; its own message replaces this one when it sent one.)\n\nThe text could not be replaced. (replace refused by the app without a message; a 500 when it sent no status.)\n\nThe text could not be appended. (append refused by the app without a message; a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (library_id does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_pointers": {
            "post": {
                "tags": [
                    "Library Tools"
                ],
                "summary": "See which post each account publishes next from a library, move one account's pointer, or point accounts at a post.",
                "description": "Every social account connected to a library has a pointer into the library's publishing order (`/api/library_content_order`): the position of the post it publishes next. `action` picks the operation on library `library_id`:\n- `list` (default): every account on the library with its next position and the post there.\n- `set`: moves one account's pointer (`account_id`) to `position`.\n- `reset`: points one or more accounts (`account_ids`) at post `content_id`, so they publish it next.",
                "operationId": "library_pointers",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted library id.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "What to do; see above.",
                                        "enum": [
                                            "list",
                                            "set",
                                            "reset"
                                        ],
                                        "default": "list",
                                        "example": "list"
                                    },
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted social account id whose pointer to move. Required when action is `set`.",
                                        "example": "aK3mZ8vQr1=="
                                    },
                                    "position": {
                                        "type": "integer",
                                        "description": "Position in the library's order the account publishes next, 1 to the number of posts. Required when action is `set`.",
                                        "example": 3
                                    },
                                    "account_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted social account ids: one id, a comma-separated string or an array, at most 50. Required when action is `reset`.",
                                        "example": [
                                            "aK3mZ8vQr1==",
                                            "gB9xT4nWp2=="
                                        ]
                                    },
                                    "content_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the post the accounts publish next; it must be in the library. Required when action is `reset`.",
                                        "example": "pQ8sL3vY2a=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "library_id"
                                ],
                                "example": {
                                    "library_id": "nX2k9Qp7Lw=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success` for list; the app's sentence for set, for example `Post #3 will be scheduled next on the Facebook Page Acme`; `The accounts publish that post next.` for reset."
                                        },
                                        "pointers": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "account": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "description": "list: encrypted social account id."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "list: account name."
                                                            },
                                                            "network": {
                                                                "type": "string",
                                                                "description": "list: facebook, twitter, linkedin, instagram, pinterest, google_my_business, tiktok, youtube, threads or bluesky."
                                                            },
                                                            "status": {
                                                                "type": "string",
                                                                "description": "list: active, paused or needs_reconnection."
                                                            }
                                                        }
                                                    },
                                                    "next_position": {
                                                        "type": "integer",
                                                        "description": "list: position in the library's order the account publishes next."
                                                    },
                                                    "next_post": {
                                                        "type": "object",
                                                        "description": "list: the post at that position with `id`, `message`, `title`, `url`, `image_url` and `video_url`, or `null` when the position holds no post."
                                                    }
                                                }
                                            }
                                        },
                                        "warning": {
                                            "type": "string",
                                            "description": "set: a note from the app about message variations at the new position, blank when none."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "pointers": [
                                        {
                                            "account": {
                                                "id": "aK3mZ8vQr1==",
                                                "name": "Acme",
                                                "network": "facebook",
                                                "status": "active"
                                            },
                                            "next_position": 2,
                                            "next_post": {
                                                "id": "zK5wN2hT8e==",
                                                "message": "Our summer sale ends tonight.",
                                                "title": "",
                                                "url": "",
                                                "image_url": "https://cdn.example.com/u/1/sale.jpg",
                                                "video_url": ""
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Send library_id and action as list, set or reset. (library_id is missing or does not decrypt, or action is another word.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\naccount_id is required. (set without an account_id that decrypts.)\n\nposition must be between 1 and N. (set with a position outside the library's size (N is the number of posts).)\n\nThe pointer could not be moved. (set refused by the app without a message; a 500 when it sent no status.)\n\naccount_ids and content_id are required. (reset without account_ids or content_id, or one of them does not decrypt.)\n\nAt most 50 ids per call; N were sent. (account_ids holds more than 50 ids.)\n\nThe pointers could not be reset. (reset refused by the app without a message; a 500 when it sent no status.)\n\nYou have insufficient permissions to perform this action... (list: you are not a member of the library's workspace.)\n\nThe pointers could not be read. (list failed in the app without a message; a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library, an account or the post does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and an account sits in another workspace.)\n\ncontent_id is not a post of this library. (reset with a post that sits in another library.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_share": {
            "post": {
                "tags": [
                    "Library Tools"
                ],
                "summary": "Read, create or reset a library's public share link, or email it to a client.",
                "description": "A share link opens a read-only page of library `library_id` where clients can review posts and leave comments (see `/api/library_comments`). `action` picks the operation:\n- `get` (default): whether the library has a link and its address.\n- `create`: switches the link on; a library that already has one keeps it.\n- `reset`: issues a new address; the old one stops opening.\n- `invite`: emails the link to `email`.\n\nEvery answer carries `enabled` and `url`.\n\nThe link is public: Anyone with the address can open the library page and comment as a guest. `reset` is how you revoke an address that got around.",
                "operationId": "library_share",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted library id.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "What to do; see above.",
                                        "enum": [
                                            "get",
                                            "create",
                                            "reset",
                                            "invite"
                                        ],
                                        "default": "get",
                                        "example": "get"
                                    },
                                    "email": {
                                        "type": "string",
                                        "format": "email",
                                        "description": "Address the link is mailed to. Required when action is `invite`.",
                                        "example": "client@example.com"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "library_id"
                                ],
                                "example": {
                                    "library_id": "nX2k9Qp7Lw=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`; `Share link created.`; `Share link reset; the old address no longer opens.`; `Invitation sent to client@example.com.`"
                                        },
                                        "enabled": {
                                            "type": "boolean",
                                            "description": "Whether the library has a share link."
                                        },
                                        "url": {
                                            "type": "string",
                                            "description": "The public address, blank when there is no link."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Share link created.",
                                    "enabled": true,
                                    "url": "https://app.recurpost.com/libraries/aB3dE5fG7h"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Send library_id and action as get, create, reset or invite. (library_id is missing or does not decrypt, or action is another word.)\n\nemail must be a valid address. (invite without a valid email.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nThe share link could not be read. (The current link could not be read from the app; a 500 when it sent no status.)\n\nThe share link could not be created. (create refused by the app without a message; a 500 when it sent no status.)\n\nThe share link could not be reset. (reset refused by the app without a message; a 500 when it sent no status.)\n\nThe invitation could not be sent. (invite refused by the app without a message; a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This library has no share link yet; create one first. (reset or invite on a library without a link.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Ten invitations per ten minutes; try again later. (invite past the app's invitation rate. No Retry-After header is sent on this one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/library_comments": {
            "post": {
                "tags": [
                    "Library Tools"
                ],
                "summary": "List the comments on a library post, add one as a team member, or mark one read or unread.",
                "description": "Clients comment on posts through the library's share link (`/api/library_share`); team members answer in the app or here. Comments hang off the share link, so a library needs one before anything can be added. `action` picks the operation:\n- `list` (default): the comments on post `content_id`, 6 a page, each marked guest or team and read or unread.\n- `add`: posts `text` on `content_id` under your name.\n- `mark`: sets comment `comment_id` read (default) or unread (`unread=true`).\n\nWho the comment is from: add signs the comment with your account's name and `guest=false`. Clients' comments arrive with `guest=true` and `unread=true`; mark them read with `action=mark` once handled.",
                "operationId": "library_comments",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "What to do; see above.",
                                        "enum": [
                                            "list",
                                            "add",
                                            "mark"
                                        ],
                                        "default": "list",
                                        "example": "list"
                                    },
                                    "content_id": {
                                        "type": "string",
                                        "description": "Encrypted library post id. Required when action is `list` or `add`; ignored for mark, which finds the post from the comment.",
                                        "example": "pQ8sL3vY2a=="
                                    },
                                    "text": {
                                        "type": "string",
                                        "description": "Comment text, 1 to 2000 characters. Required when action is `add`.",
                                        "example": "Updated the image as requested."
                                    },
                                    "comment_id": {
                                        "type": "integer",
                                        "description": "Plain integer id of the comment, from the list. Required when action is `mark`.",
                                        "example": 512
                                    },
                                    "unread": {
                                        "type": "boolean",
                                        "description": "mark: `true` marks the comment unread, `false` or missing marks it read.",
                                        "default": "false",
                                        "example": false
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Page of the list, from 1; 6 comments a page. Read when action is `list`.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success` for list; `Comment added.`; `Comment marked read.` or `Comment marked unread.`"
                                        },
                                        "page": {
                                            "type": "integer",
                                            "description": "list and add: the page returned (1 after add)."
                                        },
                                        "per_page": {
                                            "type": "integer",
                                            "description": "list and add: always 6."
                                        },
                                        "comments": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain integer comment id, used in mark."
                                                    },
                                                    "by": {
                                                        "type": "string",
                                                        "description": "Name the comment was left under."
                                                    },
                                                    "guest": {
                                                        "type": "boolean",
                                                        "description": "`true` for a client through the share link, `false` for a team member."
                                                    },
                                                    "text": {
                                                        "type": "string",
                                                        "description": "The comment."
                                                    },
                                                    "unread": {
                                                        "type": "boolean",
                                                        "description": "Whether it is still marked unread."
                                                    },
                                                    "at": {
                                                        "type": "string",
                                                        "description": "When it was left, `YYYY-MM-DD HH:MM:SS`."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "page": 1,
                                    "per_page": 6,
                                    "comments": [
                                        {
                                            "id": 512,
                                            "by": "Jane Client",
                                            "guest": true,
                                            "text": "Can we use the other photo here?",
                                            "unread": true,
                                            "at": "2026-10-22 09:14:00"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "action must be list, add or mark. (action is another word.)\n\ntext must be 1 to 2000 characters. (add with a blank text or one longer than 2000 characters.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\ncontent_id is required. (list or add without a content_id that decrypts.)\n\nThe comment could not be updated. (mark refused by the app without a message; a 500 when it sent no status.)\n\nThe comments could not be read. (list or add failed in the app without a message; a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The post does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nComment not found. (mark with a comment_id that does not exist or belongs to a library outside this workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The post's library has no share link; comments hang off it. Create one with library_share first. (add on a post whose library has no share link in this workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/schedule_list": {
            "post": {
                "tags": [
                    "Schedules"
                ],
                "summary": "List every time slot of the workspace, optionally for one library or account.",
                "description": "Returns the workspace's time slots as a flat list, one entry per library, account, day and time. `library_id` and `account_id` narrow it; both accept one id or several. A workspace with no connected account answers an empty list.\nA daily slot created in the app or with `/api/schedule_create` is stored as seven weekly slots, so `frequency` is always `weekly` or `monthly`.\n\nFilters are applied after the read: `library_id` and `account_id` filter the full list on the API side; an id that belongs to someone else simply matches nothing.",
                "operationId": "schedule_list",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted library id(s) from `/api/library_list`: one id, a comma-separated string or an array. Only slots of these libraries are returned.",
                                        "example": "pQ8rS2tU4v=="
                                    },
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted social account id(s) from `/api/social_account_list`: one id, a comma-separated string or an array. Only slots of these accounts are returned.",
                                        "example": "aB3dE5fG7h=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "schedules": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted slot id for `/api/schedule_update` and `/api/schedule_delete`."
                                                    },
                                                    "library": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "description": "Encrypted library id."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Library name."
                                                            }
                                                        }
                                                    },
                                                    "account": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "description": "Encrypted social account id."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Account display name."
                                                            },
                                                            "network": {
                                                                "type": "string",
                                                                "description": "`facebook`, `twitter`, `linkedin`, `instagram`, `pinterest`, `google_my_business`, `tiktok`, `youtube`, `threads` or `bluesky`."
                                                            }
                                                        }
                                                    },
                                                    "frequency": {
                                                        "type": "string",
                                                        "description": "`weekly` or `monthly`."
                                                    },
                                                    "day": {
                                                        "type": "integer",
                                                        "description": "1 (Monday) to 7 (Sunday) for a weekly slot, 1 to 31 for a monthly slot."
                                                    },
                                                    "time": {
                                                        "type": "string",
                                                        "description": "`HH:MM` in the account's timezone, or `null` when `best_time` is true."
                                                    },
                                                    "best_time": {
                                                        "type": "boolean",
                                                        "description": "`true` when the slot publishes at the account's calculated best time instead of a fixed time."
                                                    },
                                                    "week_of_month": {
                                                        "type": "integer",
                                                        "description": "For weekly slots: 0 every week, 1 to 4 only in that week of the month, 99 only in the last week of the month."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "schedules": [
                                        {
                                            "id": "sC4hE6dU8l==",
                                            "library": {
                                                "id": "pQ8rS2tU4v==",
                                                "name": "Evergreen tips"
                                            },
                                            "account": {
                                                "id": "aB3dE5fG7h==",
                                                "name": "Acme Store",
                                                "network": "facebook"
                                            },
                                            "frequency": "weekly",
                                            "day": 3,
                                            "time": "09:30",
                                            "best_time": false,
                                            "week_of_month": 0
                                        },
                                        {
                                            "id": "tD5iF7eV9m==",
                                            "library": {
                                                "id": "pQ8rS2tU4v==",
                                                "name": "Evergreen tips"
                                            },
                                            "account": {
                                                "id": "kL9mN1oP3q==",
                                                "name": "@acmestore",
                                                "network": "instagram"
                                            },
                                            "frequency": "monthly",
                                            "day": 15,
                                            "time": null,
                                            "best_time": true,
                                            "week_of_month": 0
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (library_id or account_id was sent and does not decrypt to an id.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (You are not the owner or an active member of that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app could not read the schedules; the app's own error text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/schedule_create": {
            "post": {
                "tags": [
                    "Schedules"
                ],
                "summary": "Add time slots for a library on one or several accounts.",
                "description": "Adds the same set of slots for `library_id` on every account in `account_id`. Each slot has a `frequency` of `daily`, `weekly` or `monthly`, a `day` (1 to 7 for weekly, 1 to 31 for monthly, ignored for daily) and either a fixed `time` as `HH:MM` or `best_time` true. A daily slot is stored as seven weekly slots, one per weekday.\nSlots are checked against the plan's per-account post slot limit before anything is created. When a slot falls later today the app queues the library's next post for it straight away.\n\nTimes are local to the account: `time` is read in each account's timezone (the workspace owner's when the account has none). The same request on accounts in different zones publishes at the same local hour in each.\n\nDuplicates: Adding a slot that already exists for the same library, account, day and time creates a second one; delete the extra with `/api/schedule_delete`.",
                "operationId": "schedule_create",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted library id from `/api/library_list`. Exactly one.",
                                        "example": "pQ8rS2tU4v=="
                                    },
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted social account id(s) from `/api/social_account_list`: one id, a comma-separated string or an array, at most 50. The slots are created on each of them.",
                                        "example": "aB3dE5fG7h==,kL9mN1oP3q=="
                                    },
                                    "slots": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Up to 50 slot objects (an array, or a JSON string holding one). Each has `frequency` (`daily`, `weekly` or `monthly`), `day` (1 Monday to 7 Sunday for weekly, 1 to 31 for monthly), and `time` as 24-hour `HH:MM` in the account's timezone or `best_time` true. A weekly slot may add `week_of_month`: 1 to 4 for that week only, 99 for the last week of the month, 0 or omitted for every week.",
                                        "example": [
                                            {
                                                "frequency": "weekly",
                                                "day": 3,
                                                "time": "09:30"
                                            },
                                            {
                                                "frequency": "monthly",
                                                "day": 15,
                                                "best_time": true
                                            }
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "library_id",
                                    "account_id",
                                    "slots"
                                ],
                                "example": {
                                    "library_id": "pQ8rS2tU4v==",
                                    "account_id": "aB3dE5fG7h==,kL9mN1oP3q==",
                                    "slots": [
                                        {
                                            "frequency": "weekly",
                                            "day": 3,
                                            "time": "09:30"
                                        },
                                        {
                                            "frequency": "monthly",
                                            "day": 15,
                                            "best_time": true
                                        }
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Schedule added successfully!`"
                                        },
                                        "schedule_ids": {
                                            "type": "array",
                                            "items": {
                                                "type": "string",
                                                "description": "Encrypted id of every slot created, in the app's order. A daily slot contributes seven ids per account."
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Schedule added successfully!",
                                    "schedule_ids": [
                                        "sC4hE6dU8l==",
                                        "tD5iF7eV9m==",
                                        "uE6jG8fW0n==",
                                        "vF7kH9gX1o=="
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (library_id, account_id or slots is missing or invalid, or slots is not a list.)\n\nAt most 50 ids per call; N were sent. (More than 50 accounts or more than 50 slots were sent.)\n\nEach slot needs frequency (daily, weekly or monthly), day (1-7 for weekly, 1-31 for monthly) and either time as HH:MM or best_time as true. (A slot is malformed: unknown frequency, day out of range, or a time that is not HH:MM (single-digit hours such as 9:00 are refused).)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nSomething went wrong (The app refused the slots for another reason; its own error text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library or one of the accounts does not belong to the workspace owner.)\n\nThese accounts have no post slots left on your plan: Acme Store, @acmestore. Upgrade the plan or remove some time slots. (The new slots would take the named accounts over the plan's per-account slot limit. Nothing is created.)\n\nYou have more time slots than what your plan offers. Please upgrade your plan or delete some time slots. (The plan's overall slot limit is reached.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (You are not the owner or an active member of that workspace.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and an account sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/schedule_update": {
            "post": {
                "tags": [
                    "Schedules"
                ],
                "summary": "Change one slot's time, switch it to best time, or move it to another library.",
                "description": "Updates a single slot. Send `time` for a fixed time or `best_time` true for the account's best time; one of the two is required. `library_id` moves the slot to another library of the same owner. The day and frequency of a slot cannot be changed; delete it and create a new one instead.",
                "operationId": "schedule_update",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted slot id from `/api/schedule_list` or `/api/schedule_create`.",
                                        "example": "sC4hE6dU8l=="
                                    },
                                    "time": {
                                        "type": "string",
                                        "description": "New time as 24-hour `HH:MM` in the account's timezone. Required unless `best_time` is true; ignored when it is.",
                                        "example": "10:15"
                                    },
                                    "best_time": {
                                        "type": "boolean",
                                        "description": "`true` publishes the slot at the account's calculated best time.",
                                        "enum": [
                                            true,
                                            false
                                        ],
                                        "default": "false",
                                        "example": false
                                    },
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library the slot should feed from. Defaults to the slot's current library.",
                                        "example": "pQ8rS2tU4v=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": "sC4hE6dU8l=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Schedule updated successfully`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Schedule updated successfully"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or does not decrypt to an id.)\n\nSend time as HH:MM or best_time as true. (Neither a valid time nor best_time true was sent.)\n\nlibrary_id is invalid. (library_id was sent and does not decrypt to an id.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The slot or the library does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (You are not the owner or an active member of that workspace.)\n\nSchedule not found. (The slot does not exist, or workspace_id was sent and the slot's account sits in another workspace.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app could not update the slot; its own error text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/schedule_delete": {
            "post": {
                "tags": [
                    "Schedules"
                ],
                "summary": "Delete one slot, every slot of a library, or every slot of an account.",
                "description": "Deletes slots by exactly one selector: `id` removes one slot, `library_id` every slot of that library, `account_id` every slot of that account. Each slot is deleted through the app, which also cancels the queued posts that slot had produced. Slots are deleted one by one; after the first success a later failure is skipped and the count tells how many went.\n\nQueued posts go with the slot: Deleting a slot cancels the library posts already queued for it, exactly as deleting the slot in the app does. Posts that were already published are not touched.",
                "operationId": "schedule_delete",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted slot id. Required when neither `library_id` nor `account_id` is sent.",
                                        "example": "sC4hE6dU8l=="
                                    },
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted library id: deletes every slot of that library (in the named workspace when `workspace_id` is sent, otherwise across the owner's workspaces).",
                                        "example": "pQ8rS2tU4v=="
                                    },
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted social account id: deletes every slot of that account.",
                                        "example": "aB3dE5fG7h=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`N schedule(s) deleted.`"
                                        },
                                        "deleted": {
                                            "type": "integer",
                                            "description": "Number of slots removed."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "3 schedule(s) deleted.",
                                    "deleted": 3
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Send exactly one of id, library_id or account_id. (None or more than one selector was sent, or the one sent does not decrypt to an id.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nThe schedule could not be deleted. (The app refused the very first slot; its own error text and status are relayed when it sent them.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The slot, library or account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (You are not the owner or an active member of that workspace.)\n\nSchedule not found. (id names a slot that does not exist, or workspace_id was sent and the slot's account sits in another workspace.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account sits in another workspace.)\n\nNo schedule found. (The library or account has no slots.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/schedule_calendar": {
            "post": {
                "tags": [
                    "Schedules"
                ],
                "summary": "The week or month view of the schedule: every day with its slots.",
                "description": "Returns the slots of the workspace laid out by day, as the Schedules page shows them: with `frequency=weekly` (the default) seven entries, Monday to Sunday; with `monthly` 31 entries, one per day of the month. Each day carries its slots in the slot shape of `/api/schedule_list`, so an empty day is a `slots` list with nothing in it. Filter by accounts, libraries or both.\n\nSame data as schedule_list: Weekly and monthly slots are separate lists; a weekly view never shows monthly slots and the other way round. `/api/schedule_list` returns both flat.",
                "operationId": "schedule_calendar",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "frequency": {
                                        "type": "string",
                                        "description": "`weekly` for the 7-day view, `monthly` for the 31-day view. Case does not matter.",
                                        "enum": [
                                            "weekly",
                                            "monthly"
                                        ],
                                        "default": "weekly",
                                        "example": "weekly"
                                    },
                                    "account_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted social account ids from `/api/social_account_list`: one id, a comma-separated string or an array. Only slots of these accounts are returned.",
                                        "example": [
                                            "aB3dE5fG7h=="
                                        ]
                                    },
                                    "library_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted library ids from `/api/library_list`: one id, a comma-separated string or an array. Only slots of these libraries are returned.",
                                        "example": [
                                            "pQ8rS2tU4v=="
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "frequency": {
                                            "type": "string",
                                            "description": "`weekly` or `monthly`, as asked."
                                        },
                                        "total_slots": {
                                            "type": "integer",
                                            "description": "Slots across every day of the view."
                                        },
                                        "days": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "day": {
                                                        "type": "integer",
                                                        "description": "1 (Monday) to 7 (Sunday) for weekly, 1 to 31 for monthly. Every day is present."
                                                    },
                                                    "slots": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "object",
                                                            "description": "The slots of that day, each in the shape of `schedules[]` of `/api/schedule_list` (`id, library, account, frequency, day, time, best_time, week_of_month`)."
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "frequency": "weekly",
                                    "total_slots": 2,
                                    "days": [
                                        {
                                            "day": 1,
                                            "slots": []
                                        },
                                        {
                                            "day": 2,
                                            "slots": []
                                        },
                                        {
                                            "day": 3,
                                            "slots": [
                                                {
                                                    "id": "sC4hE6dU8l==",
                                                    "library": {
                                                        "id": "pQ8rS2tU4v==",
                                                        "name": "Evergreen tips"
                                                    },
                                                    "account": {
                                                        "id": "aB3dE5fG7h==",
                                                        "name": "Acme Store",
                                                        "network": "facebook"
                                                    },
                                                    "frequency": "weekly",
                                                    "day": 3,
                                                    "time": "09:30",
                                                    "best_time": false,
                                                    "week_of_month": 0
                                                },
                                                {
                                                    "id": "tD5iF7eV9m==",
                                                    "library": {
                                                        "id": "pQ8rS2tU4v==",
                                                        "name": "Evergreen tips"
                                                    },
                                                    "account": {
                                                        "id": "kL9mN1oP3q==",
                                                        "name": "@acmestore",
                                                        "network": "twitter"
                                                    },
                                                    "frequency": "weekly",
                                                    "day": 3,
                                                    "time": null,
                                                    "best_time": true,
                                                    "week_of_month": 0
                                                }
                                            ]
                                        },
                                        {
                                            "day": 4,
                                            "slots": []
                                        },
                                        {
                                            "day": 5,
                                            "slots": []
                                        },
                                        {
                                            "day": 6,
                                            "slots": []
                                        },
                                        {
                                            "day": 7,
                                            "slots": []
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nfrequency must be weekly or monthly. (frequency is another word.)\n\naccount_ids holds an invalid id. (A value in account_ids does not decrypt to an id.)\n\nlibrary_ids holds an invalid id. (A value in library_ids does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (An account or library in the filter is not the workspace owner's.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (You are not the owner or an active member of that workspace.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and an account in the filter is not in that workspace.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and a library in the filter is not in that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app could not read the schedules; its own text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/schedule_copy": {
            "post": {
                "tags": [
                    "Schedules"
                ],
                "summary": "Copy one account's schedule slots to other accounts.",
                "description": "Adds to each account in `to_account_ids` a copy of the slots of `from_account_id`: the same libraries, days and times. `frequency` picks the weekly or the monthly slots, `day` narrows the copy to one day, `library_ids` to some libraries. Existing slots of the target accounts stay; the copies come on top. A copied slot that falls later today queues a post straight away, as a new slot does in the app.\n\nCopies add, they do not replace: Running the same copy twice doubles the slots on the target accounts. Check with `/api/schedule_list` first and remove extras with `/api/schedule_delete`.\n\nTimes stay as wall-clock times: A slot copied from a 09:30 account is a 09:30 slot on the target, read in the target account's timezone.",
                "operationId": "schedule_copy",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "from_account_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the account whose slots are copied, from `/api/social_account_list`.",
                                        "example": "aB3dE5fG7h=="
                                    },
                                    "to_account_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted ids of the accounts that receive the copies: one id, a comma-separated string or an array, at most 50, without the source account.",
                                        "example": [
                                            "kL9mN1oP3q=="
                                        ]
                                    },
                                    "library_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted library ids: only slots of these libraries are copied. Left out, every library's slots are.",
                                        "example": [
                                            "pQ8rS2tU4v=="
                                        ]
                                    },
                                    "frequency": {
                                        "type": "string",
                                        "description": "`weekly` copies the weekly slots, `monthly` the monthly ones. Case does not matter.",
                                        "enum": [
                                            "weekly",
                                            "monthly"
                                        ],
                                        "default": "weekly",
                                        "example": "weekly"
                                    },
                                    "day": {
                                        "type": "string",
                                        "description": "`all` for every day, or one day: 1 (Monday) to 7 (Sunday) for weekly, 1 to 31 for monthly.",
                                        "default": "all",
                                        "example": "all"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "from_account_id",
                                    "to_account_ids"
                                ],
                                "example": {
                                    "from_account_id": "aB3dE5fG7h==",
                                    "to_account_ids": [
                                        "kL9mN1oP3q=="
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Schedules copied.`"
                                        },
                                        "copied_to": {
                                            "type": "array",
                                            "items": {
                                                "type": "string",
                                                "description": "Encrypted ids of the accounts that received the copies, as sent."
                                            }
                                        },
                                        "queued_now": {
                                            "type": "integer",
                                            "description": "Posts queued straight away for copied slots that fall later today."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Schedules copied.",
                                    "copied_to": [
                                        "kL9mN1oP3q=="
                                    ],
                                    "queued_now": 2
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nfrom_account_id is required. (from_account_id is missing or does not decrypt to one id.)\n\nto_account_ids must hold at least one other account. (to_account_ids is empty, does not decrypt, or contains the source account.)\n\nAt most 50 ids per call; N were sent. (More than 50 target accounts; N is the count sent.)\n\nlibrary_ids holds an invalid id. (A value in library_ids does not decrypt to an id.)\n\nfrequency must be weekly or monthly. (frequency is another word.)\n\nday must be all or 1 to 7. (day is outside the range of the frequency; the message says 31 for monthly.)\n\nSomething went wrong (The app could not copy; its own text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The source, a target or a library is not the workspace owner's.)\n\nYou are trying to copy more schedules than what your plan offers. Please upgrade your plan or delete some time slots. (The copies would exceed the plan's slot allowance (the text says purchase a plan on a trial).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (You are not the owner or an active member of that workspace.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and an account is not in that workspace.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and a library is not in that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/schedule_remaining": {
            "post": {
                "tags": [
                    "Schedules"
                ],
                "summary": "How many more posts each account may publish on a day.",
                "description": "The plan's daily limit per account and, for each account of the workspace, how many posts it may still publish on the day asked for: the limit minus what is already queued or published on that date. `day` names a weekday and means its next occurrence (today when it is that weekday); without it the count is for today. `account_ids` narrows the list.\n\nTrial accounts: On a free trial the per-account number is also capped by the trial's lifetime post allowance, so `remaining` can be lower than `daily_limit` minus the day's posts.\n\nSame limit the queue enforces: `/api/schedule_create` and the queue endpoints refuse a post once an account's day is full; use this call to pick a day with room. `/api/account_limits` gives the same picture per date.",
                "operationId": "schedule_remaining",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "day": {
                                        "type": "integer",
                                        "description": "Weekday 1 (Monday) to 7 (Sunday); the next date that falls on it is counted. Left out, today is.",
                                        "example": 3
                                    },
                                    "account_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted social account ids from `/api/social_account_list`: one id, a comma-separated string or an array. Left out, every account of the workspace is listed.",
                                        "example": [
                                            "aB3dE5fG7h=="
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "daily_limit": {
                                            "type": "integer",
                                            "description": "Posts one account may publish per day under the owner's plan: the plan's schedule slots plus its one-off posts plus 10 for each extra daily posts add-on."
                                        },
                                        "accounts": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted social account id."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Account display name."
                                                    },
                                                    "network": {
                                                        "type": "string",
                                                        "description": "`facebook`, `twitter`, `linkedin`, `instagram`, `pinterest`, `google_my_business`, `tiktok`, `youtube`, `threads` or `bluesky`."
                                                    },
                                                    "remaining": {
                                                        "type": "integer",
                                                        "description": "Posts the account may still publish on that day; 0 or less when the day is full."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "daily_limit": 25,
                                    "accounts": [
                                        {
                                            "id": "aB3dE5fG7h==",
                                            "name": "Acme Store",
                                            "network": "facebook",
                                            "remaining": 7
                                        },
                                        {
                                            "id": "kL9mN1oP3q==",
                                            "name": "@acmestore",
                                            "network": "twitter",
                                            "remaining": 25
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nday must be 1 (Monday) to 7 (Sunday). (day is sent and is not 1 to 7.)\n\naccount_ids holds an invalid id. (A value in account_ids does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (An account in the filter is not the workspace owner's.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (You are not the owner or an active member of that workspace.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and an account in the filter is not in that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app could not compute the counts; its own text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/schedule_move_slot": {
            "post": {
                "tags": [
                    "Schedules"
                ],
                "summary": "Move one slot to another day or time.",
                "description": "Moves an existing slot to a new `day` and `time`, or to the account's best time with `best_time=true`, keeping its library and account. The day must fit the slot's frequency: 1 to 7 for a weekly slot, 1 to 31 for a monthly one. As in the app, the posts already queued from the old slot are cancelled, and when the new slot falls later today it is filled at once.\n\nQueued posts are cancelled: Posts the old slot had already placed in the queue are removed and the libraries pick again for the new slot. Edited queue posts from that slot are lost too, as when the slot is dragged on the Schedules page.\n\nWeek of month is kept: A weekly slot limited to one week of the month keeps that limit; this call changes only the day and the time.",
                "operationId": "schedule_move_slot",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted slot id from `schedules[].id` of `/api/schedule_list`.",
                                        "example": "sC4hE6dU8l=="
                                    },
                                    "day": {
                                        "type": "integer",
                                        "description": "New day: 1 (Monday) to 7 (Sunday) for a weekly slot, 1 to 31 for a monthly slot. Left out, the slot keeps its day.",
                                        "example": 5
                                    },
                                    "time": {
                                        "type": "string",
                                        "description": "Required unless `best_time` is true: new time as `HH:MM`, 24-hour, in the account's timezone.",
                                        "example": "14:30"
                                    },
                                    "best_time": {
                                        "type": "boolean",
                                        "description": "`true` publishes at the account's calculated best time instead of a fixed time; `time` is then ignored.",
                                        "example": false
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. When sent, the slot must be in this workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": "sC4hE6dU8l=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Slot moved; its queued posts were cancelled and the new slot is filled when it falls today.`"
                                        },
                                        "schedule": {
                                            "type": "object",
                                            "description": "The slot after the move, in the shape of `schedules[]` of `/api/schedule_list` (`id, library, account, frequency, day, time, best_time, week_of_month`)."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Slot moved; its queued posts were cancelled and the new slot is filled when it falls today.",
                                    "schedule": {
                                        "id": "sC4hE6dU8l==",
                                        "library": {
                                            "id": "pQ8rS2tU4v==",
                                            "name": "Evergreen tips"
                                        },
                                        "account": {
                                            "id": "aB3dE5fG7h==",
                                            "name": "Acme Store",
                                            "network": "facebook"
                                        },
                                        "frequency": "weekly",
                                        "day": 5,
                                        "time": "14:30",
                                        "best_time": false,
                                        "week_of_month": 0
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nday must be 1 to 7 for this weekly slot. (day is outside the slot's range; the message says 1 to 31 for a monthly slot.)\n\ntime must be HH:MM, or send best_time=true. (best_time is not true and time is missing or not HH:MM.)\n\nSomething went wrong (The app could not move the slot; its own text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (You are not the owner or an active member of that workspace.)\n\nid is not a schedule of this workspace. (id is missing, does not decrypt, is not the workspace owner's slot, or is outside the named workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/feed_list": {
            "post": {
                "tags": [
                    "RSS Feeds"
                ],
                "summary": "List the RSS feeds of the workspace, or of one library.",
                "description": "Returns every feed attached to a library of the workspace, sorted by feed title, with the library it feeds, whether new articles are approved automatically and how many articles are waiting for approval. Pass `library_id` to list the feeds of one library only. A feed attached to several libraries appears once per library.",
                "operationId": "feed_list",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted library id from `/api/library_list`. Only that library's feeds are returned.",
                                        "example": "pQ8rS2tU4v=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "feeds": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted feed id for `/api/feed_status`."
                                                    },
                                                    "url": {
                                                        "type": "string",
                                                        "description": "The feed URL as stored."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Feed title read from the feed itself."
                                                    },
                                                    "library": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "description": "Encrypted id of the library this entry feeds."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Library name."
                                                            }
                                                        }
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "`active` when the feed is being read, `paused` otherwise."
                                                    },
                                                    "approval": {
                                                        "type": "string",
                                                        "description": "`auto` when new articles go straight into the library, `manual` when they wait for approval."
                                                    },
                                                    "top_of_queue": {
                                                        "type": "boolean",
                                                        "description": "`true` when approved articles are placed at the front of the library's queue."
                                                    },
                                                    "pending_count": {
                                                        "type": "integer",
                                                        "description": "Articles fetched from the feed and not yet approved for this library."
                                                    },
                                                    "added_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When the feed was attached to the library, server time (UTC). Blank for very old entries."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "feeds": [
                                        {
                                            "id": "fG1hJ3kL5m==",
                                            "url": "https://blog.example.com/feed",
                                            "title": "Example Blog",
                                            "library": {
                                                "id": "pQ8rS2tU4v==",
                                                "name": "Blog posts"
                                            },
                                            "status": "active",
                                            "approval": "manual",
                                            "top_of_queue": true,
                                            "pending_count": 3,
                                            "added_at": "2026-10-01 10:00:00"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "library_id is invalid. (library_id was sent and does not decrypt to an id.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (You are not the owner or an active member of that workspace.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The feeds could not be read. (The app failed to read the feeds; its own error text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/feed_create": {
            "post": {
                "tags": [
                    "RSS Feeds"
                ],
                "summary": "Attach an RSS feed to a library and fetch its current articles.",
                "description": "Reads the feed at `url`, attaches it to `library_id` and stores its current articles as pending posts for that library. The feed is fetched during the call, so it can take several seconds. From then on new articles are picked up by RecurPost's periodic feed check.\n`message_template` is the text of every post made from an article. It may contain placeholders written as `{|||name|||}`, which are replaced per article: `{|||title|||}`, `{|||description|||}`, `{|||post_url|||}`, `{|||link|||}`, `{|||pubDate|||}`, `{|||author|||}` and `{|||categories|||}`. A YouTube channel or user URL is turned into its feed automatically.\n\nArticles link to their page: Every post made from an article links to the article's own URL, so the networks that show link previews show the article. `message_template` is the text above that link; leave it out to post the link alone.\n\nAuto approve acts at once: With `auto_approve` true the articles fetched during this call are added to the library immediately, each taking a library post slot on the plan.",
                "operationId": "feed_create",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public http or https address of the RSS or Atom feed, or of a page that links to one.",
                                        "example": "https://blog.example.com/feed"
                                    },
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library the articles go into, from `/api/library_list`.",
                                        "example": "pQ8rS2tU4v=="
                                    },
                                    "message_template": {
                                        "type": "string",
                                        "description": "Post text built for each article, with `{|||name|||}` placeholders (see above). Optional: without it each article is posted as its link alone, with the preview the network builds from the page.",
                                        "example": "{|||title|||} {|||post_url|||}"
                                    },
                                    "auto_approve": {
                                        "type": "boolean",
                                        "description": "`true` adds articles to the library without review, including the ones fetched now; `false` leaves them pending until approved in the app.",
                                        "enum": [
                                            true,
                                            false
                                        ],
                                        "default": "false",
                                        "example": false
                                    },
                                    "top_of_queue": {
                                        "type": "boolean",
                                        "description": "`true` places approved articles at the front of the library's queue so they publish next.",
                                        "enum": [
                                            true,
                                            false
                                        ],
                                        "default": "false",
                                        "example": false
                                    },
                                    "host_images": {
                                        "type": "boolean",
                                        "description": "`true` copies article images to RecurPost storage instead of linking to the source.",
                                        "enum": [
                                            true,
                                            false
                                        ],
                                        "default": "false",
                                        "example": false
                                    },
                                    "live_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "`YYYY-MM-DD`. Posts made from the feed stay drafts and start publishing on this date.",
                                        "example": "2026-11-01"
                                    },
                                    "expire_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "`YYYY-MM-DD`. Posts made from the feed stop recurring after this date.",
                                        "example": "2026-12-31"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "url",
                                    "library_id"
                                ],
                                "example": {
                                    "url": "https://blog.example.com/feed",
                                    "library_id": "pQ8rS2tU4v=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Feed added.`"
                                        },
                                        "id": {
                                            "type": "string",
                                            "description": "Encrypted feed id. Use it with `library_id` in `/api/feed_status`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Feed added.",
                                    "id": "fG1hJ3kL5m=="
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "url must be a public http or https address. (url is missing, not a URL, not http(s), or points at a private or local address.)\n\nlibrary_id is required. (library_id is missing or does not decrypt to an id.)\n\nlive_date and expire_date must be YYYY-MM-DD. (One of the dates is in another format or is not a real date.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nSorry, we can't add this feed right now. Please try later. (The feed record could not be stored.)\n\nSorry, something went wrong. Please try again later. (Reading or storing the feed raised an error.)\n\nThe feed could not be added. (The app answered without a message; a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library does not belong to the workspace owner.)\n\nYou have maximum allowed number of feeds for your plan. Please upgrade your plan to add more feeds. (The owner's plan allows no more feeds.)\n\nYou have maximum allowed number of updates in your library. Please upgrade your plan or delete few updates to add new ones. (The owner's library post limit is reached.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (You are not the owner or an active member of that workspace.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This feed is already there. (The same feed is already attached to that library.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Sorry, we cannot find an RSS feed on that page. Please give a direct link to the feed. (The URL could be fetched but no feed or no articles were found in it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/feed_status": {
            "post": {
                "tags": [
                    "RSS Feeds"
                ],
                "summary": "Pause, resume or delete a feed of a library.",
                "description": "Changes one feed of one library. `pause` stops new articles from being fetched for it, `resume` starts again (the plan's feed limit is checked), `delete` removes the feed. The feed must be attached to the given library and both must belong to the workspace owner.\n\nOne feed per library: Adding the same URL to another library creates a separate feed with its own id, so `delete` removes this library's feed and its pending (not yet approved) articles only. Articles already approved into the library stay.",
                "operationId": "feed_status",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted feed id from `/api/feed_list` or `/api/feed_create`.",
                                        "example": "fG1hJ3kL5m=="
                                    },
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library the feed is attached to.",
                                        "example": "pQ8rS2tU4v=="
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "What to do with the feed, case-insensitive.",
                                        "enum": [
                                            "pause",
                                            "resume",
                                            "delete"
                                        ],
                                        "example": "pause"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id",
                                    "library_id",
                                    "action"
                                ],
                                "example": {
                                    "id": "fG1hJ3kL5m==",
                                    "library_id": "pQ8rS2tU4v==",
                                    "action": "pause"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Feed paused.`, `Feed resumed.` or `Feed deleted.`"
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Feed paused."
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Send id, library_id and action as pause, resume or delete. (id or library_id is missing or does not decrypt, or action is not one of the three words.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nThe feed could not be updated. (The app refused the change; its own error text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library does not belong to the workspace owner.)\n\nYou have maximum allowed number of feeds for your plan. Please upgrade your plan to resume this feed. (action is resume and the owner's plan has no feed slot left.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (You are not the owner or an active member of that workspace.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\nFeed not found in this library. (The feed is not attached to that library for the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/feed_update": {
            "post": {
                "tags": [
                    "RSS Feeds"
                ],
                "summary": "Change a feed's settings in one library, or move it to another library.",
                "description": "Changes how feed `id` fills library `library_id`. Every setting is optional and a setting left out keeps its value: `auto_approve`, `top_of_queue`, `host_images`, `live_date`, `expire_date` and `message_template` (with the `{|||name|||}` placeholders of `/api/feed_create`). `new_library_id` moves the feed, with its waiting items, to another library of the owner. The answer is the feed's settings after the change.\n\nauto_approve on approves the backlog: Turning `auto_approve` on moves every item waiting in `/api/feed_items` into the library in this call, each taking a library post slot on the plan. Decide the backlog with `/api/feed_item_decide` first if you want to keep some out.",
                "operationId": "feed_update",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted feed id from `/api/feed_list`.",
                                        "example": "fG1hJ3kL5m=="
                                    },
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library the feed currently fills.",
                                        "example": "pQ8rS2tU4v=="
                                    },
                                    "new_library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of another library of the owner to move the feed into.",
                                        "example": "bT4r8Vz1Kc=="
                                    },
                                    "auto_approve": {
                                        "type": "boolean",
                                        "description": "`true` adds new articles to the library without review; `false` leaves them waiting in `/api/feed_items`. Switching it on approves every waiting item at once.",
                                        "enum": [
                                            true,
                                            false
                                        ],
                                        "example": false
                                    },
                                    "top_of_queue": {
                                        "type": "boolean",
                                        "description": "`true` places approved articles at the front of the library's queue.",
                                        "enum": [
                                            true,
                                            false
                                        ],
                                        "example": false
                                    },
                                    "host_images": {
                                        "type": "boolean",
                                        "description": "`true` copies article images to RecurPost storage instead of linking to the source.",
                                        "enum": [
                                            true,
                                            false
                                        ],
                                        "example": true
                                    },
                                    "live_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "`YYYY-MM-DD` from which posts made from the feed publish; blank clears it.",
                                        "example": "2026-12-01"
                                    },
                                    "expire_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "`YYYY-MM-DD` after which posts made from the feed stop recurring; blank clears it.",
                                        "example": "2027-01-31"
                                    },
                                    "message_template": {
                                        "type": "string",
                                        "description": "Post text built for each article, at most 5000 characters, with `{|||title|||}`, `{|||description|||}`, `{|||post_url|||}`, `{|||link|||}`, `{|||pubDate|||}`, `{|||author|||}` and `{|||categories|||}` placeholders. Blank posts the article link alone.",
                                        "example": "{|||title|||} {|||post_url|||}"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id",
                                    "library_id"
                                ],
                                "example": {
                                    "id": "fG1hJ3kL5m==",
                                    "library_id": "pQ8rS2tU4v=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Feed updated.`"
                                        },
                                        "feed": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted feed id."
                                                },
                                                "url": {
                                                    "type": "string",
                                                    "description": "The feed address."
                                                },
                                                "title": {
                                                    "type": "string",
                                                    "description": "Title read from the feed."
                                                },
                                                "library_id": {
                                                    "type": "string",
                                                    "description": "Encrypted id of the library the feed now fills."
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "active or paused."
                                                },
                                                "auto_approve": {
                                                    "type": "boolean",
                                                    "description": "Whether new articles skip review."
                                                },
                                                "top_of_queue": {
                                                    "type": "boolean",
                                                    "description": "Whether approved articles go to the front of the queue."
                                                },
                                                "live_date": {
                                                    "type": "string",
                                                    "description": "`YYYY-MM-DD` or blank."
                                                },
                                                "expire_date": {
                                                    "type": "string",
                                                    "description": "`YYYY-MM-DD` or blank."
                                                },
                                                "message_template": {
                                                    "type": "string",
                                                    "description": "The post text template."
                                                },
                                                "host_images": {
                                                    "type": "boolean",
                                                    "description": "Whether article images are copied to RecurPost storage."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Feed updated.",
                                    "feed": {
                                        "id": "fG1hJ3kL5m==",
                                        "url": "https://blog.example.com/feed",
                                        "title": "Example Blog",
                                        "library_id": "pQ8rS2tU4v==",
                                        "status": "active",
                                        "auto_approve": false,
                                        "top_of_queue": true,
                                        "live_date": "2026-12-01",
                                        "expire_date": "",
                                        "message_template": "{|||title|||} {|||post_url|||}",
                                        "host_images": true
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "id and library_id are required. (id or library_id is missing or does not decrypt.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nnew_library_id is invalid. (new_library_id is sent and does not decrypt.)\n\nlive_date must be YYYY-MM-DD or blank. (live_date (or expire_date, named in the message) is sent in another format or is not a real date.)\n\nmessage_template may have at most 5000 characters. (The template is longer than 5000 characters.)\n\nYou have already added this feed. (new_library_id already has this feed.)\n\nSorry, something went wrong. Please try again later. (The app could not save the feed.)\n\nThe feed could not be updated. (The app refused without a message; a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (library_id or new_library_id does not belong to the workspace owner.)\n\nYou have maximum allowed number of updates in your library. Please upgrade your plan or delete few updates to add new ones. (Switching auto_approve on would pass the owner's library post limit (the upgrade wording varies by plan).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and a library sits in another workspace.)\n\nFeed not found in this library. (The feed is not attached to library_id for this owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/feed_refresh": {
            "post": {
                "tags": [
                    "RSS Feeds"
                ],
                "summary": "Fetch the feed now and store its new articles.",
                "description": "Reads feed `id` from its source right away instead of waiting for RecurPost's periodic check, and stores the articles not seen before: as waiting items for `/api/feed_items`, or straight into library `library_id` when the feed auto-approves. The remote feed is fetched during the call, so it can take a few seconds and is limited to one refresh per feed per minute.\n\nThe minute is the clock minute: The refresh counter is per UTC clock minute, not a rolling 60 seconds: two refreshes a few seconds apart are refused only when both fall in the same minute. A refused call still counts.",
                "operationId": "feed_refresh",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted feed id from `/api/feed_list`.",
                                        "example": "fG1hJ3kL5m=="
                                    },
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library the feed fills.",
                                        "example": "pQ8rS2tU4v=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id",
                                    "library_id"
                                ],
                                "example": {
                                    "id": "fG1hJ3kL5m==",
                                    "library_id": "pQ8rS2tU4v=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Feed refreshed.` when new articles were stored, `The feed has no new items.` otherwise."
                                        },
                                        "new_items": {
                                            "type": "boolean",
                                            "description": "Whether the fetch found articles not stored before."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Feed refreshed.",
                                    "new_items": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "id and library_id are required. (id or library_id is missing or does not decrypt.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nFeed Not Found! (The app could not find the feed.)\n\nThis feed is already refreshed. (The app's own refresh guard refused the fetch.)\n\nSorry, something went wrong. Please try again later. (The source could not be read or the items could not be stored.)\n\nThe feed could not be refreshed. (The app refused without a message; a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\nFeed not found in this library. (The feed is not attached to library_id for this owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "One refresh per feed per minute. Try again in N seconds. (A second refresh of the same feed inside the same clock minute. The Retry-After header carries the seconds.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/feed_items": {
            "post": {
                "tags": [
                    "RSS Feeds"
                ],
                "summary": "The articles of a feed waiting for review in a library.",
                "description": "Lists the articles feed `id` fetched for library `library_id` that are waiting for a decision, newest first and paged. Approve or reject them with `/api/feed_item_decide` using `items[].id`. A feed that auto-approves has nothing here.",
                "operationId": "feed_items",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted feed id from `/api/feed_list`.",
                                        "example": "fG1hJ3kL5m=="
                                    },
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library the feed fills.",
                                        "example": "pQ8rS2tU4v=="
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Page, from 1.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "per_page": {
                                        "type": "integer",
                                        "description": "Items per page, 1 to 50.",
                                        "default": "20",
                                        "example": 20
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id",
                                    "library_id"
                                ],
                                "example": {
                                    "id": "fG1hJ3kL5m==",
                                    "library_id": "pQ8rS2tU4v=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`"
                                        },
                                        "page": {
                                            "type": "integer",
                                            "description": "The page returned."
                                        },
                                        "per_page": {
                                            "type": "integer",
                                            "description": "Items per page."
                                        },
                                        "total": {
                                            "type": "integer",
                                            "description": "Waiting items in the feed."
                                        },
                                        "items": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain integer item id, used in `/api/feed_item_decide`."
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "description": "What the article would post as: text, link, image or video."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Article title."
                                                    },
                                                    "text": {
                                                        "type": "string",
                                                        "description": "Post text built from the template."
                                                    },
                                                    "description": {
                                                        "type": "string",
                                                        "description": "Article summary."
                                                    },
                                                    "url": {
                                                        "type": "string",
                                                        "description": "Article address."
                                                    },
                                                    "images": {
                                                        "type": "array",
                                                        "items": [],
                                                        "description": "Image URLs found in the article."
                                                    },
                                                    "video_url": {
                                                        "type": "string",
                                                        "description": "Video URL, blank when none."
                                                    },
                                                    "published_at": {
                                                        "type": "string",
                                                        "description": "When the source published the article, as the feed stated it."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "page": 1,
                                    "per_page": 20,
                                    "total": 2,
                                    "items": [
                                        {
                                            "id": 4812,
                                            "type": "link",
                                            "title": "Planning a month of posts",
                                            "text": "Planning a month of posts https://blog.example.com/plan",
                                            "description": "How to batch your content in one sitting.",
                                            "url": "https://blog.example.com/plan",
                                            "images": [
                                                "https://blog.example.com/img/plan.jpg"
                                            ],
                                            "video_url": "",
                                            "published_at": "2026-10-20 10:00:00"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "id and library_id are required. (id or library_id is missing or does not decrypt.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nThe feed items could not be read. (The app failed without a message; a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\nFeed not found in this library. (The feed is not attached to library_id for this owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/feed_item_decide": {
            "post": {
                "tags": [
                    "RSS Feeds"
                ],
                "summary": "Approve or reject waiting feed articles, one by one or all at once.",
                "description": "Decides the articles of feed `id` waiting in library `library_id`. `action` picks the operation:\n- `approve`: copies the items in `item_ids` into the library with their text, link, images and video.\n- `reject`: removes the items in `item_ids` from the waiting list.\n- `approve_all`: moves every waiting item into the library; needs `confirm=true`. As the app's bulk approve does, it copies text, link and cover image only.\n- `reject_all`: empties the feed's list; needs `confirm=true`. As in the app, this also removes items approved earlier from the feed's list (the library posts made from them stay).\n\napprove_all drops media: Bulk approval copies each article's text, link and cover image only, as the app's Approve all does. Approve items one by one (`action=approve`) to keep every image and the video.",
                "operationId": "feed_item_decide",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted feed id from `/api/feed_list`.",
                                        "example": "fG1hJ3kL5m=="
                                    },
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library the feed fills.",
                                        "example": "pQ8rS2tU4v=="
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "What to do; see above.",
                                        "enum": [
                                            "approve",
                                            "reject",
                                            "approve_all",
                                            "reject_all"
                                        ],
                                        "example": "approve"
                                    },
                                    "item_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Plain integer item ids from `/api/feed_items`: one id, a comma-separated string or an array, at most 50; every id must be waiting in this feed and library. Required when action is `approve` or `reject`.",
                                        "example": [
                                            4812,
                                            4813
                                        ]
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be `true` when action is `approve_all` or `reject_all`.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id",
                                    "library_id",
                                    "action"
                                ],
                                "example": {
                                    "id": "fG1hJ3kL5m==",
                                    "library_id": "pQ8rS2tU4v==",
                                    "action": "approve"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`N item(s) moved to the library.`; `N item(s) removed from the feed.`; `Every waiting item moved to the library.`; `Every item removed from the feed.`"
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "2 item(s) moved to the library."
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "id and library_id are required. (id or library_id is missing or does not decrypt.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\naction must be approve, reject, approve_all or reject_all. (action is missing or another word.)\n\nitem_ids is required. (approve or reject without a positive integer in item_ids.)\n\nAt most 50 ids per call; N were sent. (item_ids holds more than 50 ids.)\n\nSend confirm=true to move every waiting item of the feed into the library. (approve_all without confirm=true. reject_all reads Send confirm=true to remove every item of the feed from its list.)\n\nThe items could not be decided. (The app refused without a message; a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library does not belong to the workspace owner.)\n\nYou have maximum allowed number of updates in your library. Please upgrade your plan or delete few updates to add new ones. (Approving would pass the owner's library post limit; messages starting You are trying to add are relayed the same way (the wording varies by plan).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library sits in another workspace.)\n\nFeed not found in this library. (The feed is not attached to library_id for this owner.)\n\nitem_ids holds ids that are not waiting in this feed and library. (An id is unknown, already decided, or belongs to another feed or library.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The feed is paused; resume it to decide its items. (The feed is paused; resume it with `/api/feed_status`.)\n\nNothing was approved: no item is waiting, or the library content limit is reached. (approve_all when the app had nothing to move or no room for it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/import_accounts": {
            "post": {
                "tags": [
                    "Import"
                ],
                "summary": "List the connected accounts the import plugin can pull posts from, with the time of the newest post fetched so far.",
                "description": "Returns the active social accounts of the workspace whose published posts can be imported. The plugin covers Facebook pages, LinkedIn company pages, Instagram business accounts, Pinterest, Google Business, Threads and Bluesky. X is left out because its API quota no longer allows the pull.\nUse the `id` of an account as `account_id` on `/api/import_posts` and `/api/import_to_library`.\n\nOnly active accounts: Disconnected or paused accounts are not listed, and a workspace with no eligible account answers 200 with an empty `accounts` array rather than an error.",
                "operationId": "import_accounts",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "accounts": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Accounts the plugin can import from. Empty when the workspace has none.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted account id. Pass it as `account_id` to the other import endpoints."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Account name as shown in RecurPost."
                                                    },
                                                    "network": {
                                                        "type": "string",
                                                        "description": "One of `facebook`, `linkedin`, `instagram`, `pinterest`, `google_my_business`, `threads`, `bluesky`."
                                                    },
                                                    "image": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Profile picture URL."
                                                    },
                                                    "last_fetched_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "Time of the newest post pulled from this account so far, in the workspace owner's timezone. `null` when nothing has been fetched yet."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "accounts": [
                                        {
                                            "id": "aB3dE5fG7h==",
                                            "name": "Acme Coffee",
                                            "network": "facebook",
                                            "image": "https://graph.facebook.com/1234567890/picture",
                                            "last_fetched_at": "2026-10-15 11:30:00"
                                        },
                                        {
                                            "id": "kL9mN1oP3q==",
                                            "name": "acmecoffee",
                                            "network": "instagram",
                                            "image": "https://scontent.cdninstagram.com/v/t51/acme.jpg",
                                            "last_fetched_at": null
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to a workspace id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app could not read the account list. The status and message are the app's own when it sent any.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/import_posts": {
            "post": {
                "tags": [
                    "Import"
                ],
                "summary": "Page through the posts one account has published that are not yet imported, 50 per page.",
                "description": "Lists the posts published on the network by one account, refreshed from the network first (as the plugin page does), so a call can take a few seconds. Posts already moved into a library are left out. The list is fixed at 50 posts per page; there is no `per_page` parameter.\nEach item's integer `id` is what `/api/import_to_library` takes in `ids`. Ids are only meaningful together with the same `account_id`.\n\nEvery call hits the network: Before answering, the app pulls the latest posts of the account from the social network. Expect a slower response than other list endpoints and avoid polling this endpoint in a tight loop.\n\nEmpty result is not an error: An account with nothing left to import answers 200 with `items: []`, `total: 0` and `total_pages: 0`.\n\nInstagram videos with licensed audio: Instagram omits the media URL of videos that use copyrighted audio. Such posts come back with `type: photo` and only their thumbnail in `image`.",
                "operationId": "import_posts",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted account id from `/api/import_accounts`. Must be an active account of one of the networks the plugin covers.",
                                        "example": "aB3dE5fG7h=="
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "Kind of post to list. `media` covers photos, videos and carousels; `doc` is LinkedIn documents. Case-insensitive.",
                                        "enum": [
                                            "all",
                                            "text",
                                            "link",
                                            "media",
                                            "doc"
                                        ],
                                        "default": "all",
                                        "example": "all"
                                    },
                                    "published_by": {
                                        "type": "string",
                                        "description": "Narrows Facebook and LinkedIn posts to the app that published them, for example `RecurPost`. Use one of the names in the `apps` array of a previous response. Letters, digits, spaces, dots, underscores and hyphens, up to 100 characters.",
                                        "example": "RecurPost"
                                    },
                                    "order": {
                                        "type": "string",
                                        "description": "`newest` lists the most recent posts first, `oldest` the earliest. Any value other than `oldest` is treated as `newest`.",
                                        "enum": [
                                            "newest",
                                            "oldest"
                                        ],
                                        "default": "newest",
                                        "example": "newest"
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Page number, starting at 1. Values below 1 are read as 1.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "account_id"
                                ],
                                "example": {
                                    "account_id": "aB3dE5fG7h=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "account": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "The `account_id` you sent."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Account name."
                                                },
                                                "network": {
                                                    "type": "string",
                                                    "description": "Network key of the account, for example `facebook`."
                                                }
                                            }
                                        },
                                        "page": {
                                            "type": "integer",
                                            "description": "The page returned."
                                        },
                                        "per_page": {
                                            "type": "integer",
                                            "description": "Always 50."
                                        },
                                        "total": {
                                            "type": "integer",
                                            "description": "Number of not yet imported posts matching the filters."
                                        },
                                        "total_pages": {
                                            "type": "integer",
                                            "description": "Number of pages at 50 per page. 0 when there is nothing to list."
                                        },
                                        "last_fetched_at": {
                                            "type": "string",
                                            "format": "date-time",
                                            "description": "Time of the newest post pulled from this account, in the workspace owner's timezone, or `null`."
                                        },
                                        "apps": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Names of the apps that published the stored posts (Facebook and LinkedIn). Any of them is a valid `published_by`."
                                            }
                                        },
                                        "items": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Posts on this page. Empty when nothing matches.",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain integer id of the fetched post. Pass it in `ids` to `/api/import_to_library`."
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "description": "Kind of post as the network reports it: `text`, `link`, `photo`, `video`, `carousel`, `album`, `doc` or a raw Facebook attachment type such as `status`."
                                                    },
                                                    "text": {
                                                        "type": "string",
                                                        "description": "Caption of the post. Empty string when there is none."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Title of a link or pin when the network provides one, otherwise empty."
                                                    },
                                                    "image": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Image or video thumbnail URL, or empty string."
                                                    },
                                                    "video": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Video URL, or empty string."
                                                    },
                                                    "link": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Shared link, or empty string. For LinkedIn documents this is the document URL."
                                                    },
                                                    "carousel": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "array",
                                                            "items": [],
                                                            "description": "Image URLs of a carousel or album post. Empty for single-media posts."
                                                        }
                                                    },
                                                    "published_by": {
                                                        "type": "string",
                                                        "description": "App that published the post, when the network reports it. Empty otherwise."
                                                    },
                                                    "posted_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When the post went live on the network, in the workspace owner's timezone. `null` when unknown."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "account": {
                                        "id": "aB3dE5fG7h==",
                                        "name": "Acme Coffee",
                                        "network": "facebook"
                                    },
                                    "page": 1,
                                    "per_page": 50,
                                    "total": 73,
                                    "total_pages": 2,
                                    "last_fetched_at": "2026-10-15 11:30:00",
                                    "apps": [
                                        "Facebook",
                                        "RecurPost"
                                    ],
                                    "items": [
                                        {
                                            "id": 48213,
                                            "type": "photo",
                                            "text": "Fresh beans just landed. Come and taste the new single origin.",
                                            "title": "",
                                            "image": "https://scontent.xx.fbcdn.net/v/t39/beans.jpg",
                                            "video": "",
                                            "link": "",
                                            "carousel": [],
                                            "published_by": "RecurPost",
                                            "posted_at": "2026-10-14 11:30:00"
                                        },
                                        {
                                            "id": 48201,
                                            "type": "album",
                                            "text": "Behind the bar this week.",
                                            "title": "",
                                            "image": "https://scontent.xx.fbcdn.net/v/t39/bar1.jpg",
                                            "video": "",
                                            "link": "",
                                            "carousel": [
                                                "https://scontent.xx.fbcdn.net/v/t39/bar1.jpg",
                                                "https://scontent.xx.fbcdn.net/v/t39/bar2.jpg"
                                            ],
                                            "published_by": "Facebook",
                                            "posted_at": "2026-10-12 09:05:00"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (account_id is missing or does not decrypt to one id.)\n\ntype must be all, text, link, media or doc. (type is not one of the allowed values.)\n\npublished_by must be one of the apps listed in the response. (published_by contains characters other than letters, digits, spaces, dots, underscores and hyphens, or is longer than 100 characters.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nThe import plugin covers Facebook pages, LinkedIn companies, Instagram business, Pinterest, Google Business, Threads and Bluesky accounts; this account is none of those. (The account is on a network the plugin does not import from, for example X or a personal LinkedIn profile.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account is not attached to that workspace.)\n\nThis account is disconnected or not found; the plugin imports from active accounts only. (The account exists but is disconnected or paused.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app could not fetch or list the posts. The status and message are the app's own when it sent any.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/import_to_library": {
            "post": {
                "tags": [
                    "Import"
                ],
                "summary": "Move a batch of fetched posts into a library, with optional caption and per-network customisation.",
                "description": "Copies the given posts of one account into a library as new library posts. Media is downloaded from the network and re-uploaded to your RecurPost storage. Posts that were imported disappear from `/api/import_posts`.\nBefore anything is written the endpoint checks the library content limit of the workspace owner: when the batch would pass it, the whole batch is refused with 403 and nothing is imported. The app itself would import part of the batch and still answer with an error, so send batches that fit.\ncustomize is an optional JSON object (or a JSON string) shaped like the plugin's customise step:\n- Caption keys at the top level: `prefix`, `suffix`, `hashtags` (array), `first_comment`. They apply to every imported post. Prefix, caption, suffix and hashtags are joined with blank lines; a hashtag without `#` gets one.\n- `networks`: an object keyed by network short code with that network's posting options. Known keys are `fb`, `ig`, `ln`, `pi`, `gmb`, `tk` and `yt`; other keys are ignored. Sending any network switches the library post to customised per-network settings.\n\nThe generic `first_comment` is stored for Facebook pages, LinkedIn and Instagram feed posts; a `first_comment` under `networks.fb`, `networks.ln` or `networks.ig` overrides it for that network. `tk` and `yt` options are applied only to imported posts that carry a video. Any other top-level key of `customize` is dropped.\n\nSize the batch to the allowance: The pre-check compares the number of ids with `plan limit - library posts already stored` for the workspace owner. On free plans variations and per-network captions count towards the stored total. Keep batches below the room left, which the 403 message reports.\n\nimported_count is the batch size: The app does not report per-post results, so `imported_count` is the number of distinct ids you sent rather than a confirmed count. Verify with the library content list if you need certainty.\n\nSlow for media-heavy batches: Every image and video is downloaded from the network and re-uploaded to your media storage during the call. Keep batches small when the posts carry videos or carousels.",
                "operationId": "import_to_library",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted account id the posts were listed from with `/api/import_posts`.",
                                        "example": "aB3dE5fG7h=="
                                    },
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library to add the posts to. Get ids from `/api/library_list`.",
                                        "example": "cD4eF6gH8i=="
                                    },
                                    "ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Plain integer `items[].id` values from `/api/import_posts`, as a JSON array or a comma-separated string. Duplicates and non-positive values are dropped; at least one id must remain.",
                                        "example": [
                                            48213,
                                            48201
                                        ]
                                    },
                                    "customize": {
                                        "type": "object",
                                        "description": "Caption and per-network options applied to every post of the batch, as a JSON object or a JSON string. See the description for the structure and the nested keys below. Omit it to import the posts as they are.",
                                        "example": {
                                            "prefix": "From our archive:",
                                            "hashtags": [
                                                "coffee",
                                                "#acme"
                                            ],
                                            "first_comment": "Visit acmecoffee.example for opening hours.",
                                            "networks": {
                                                "fb": {
                                                    "post_type": [
                                                        1,
                                                        2
                                                    ]
                                                },
                                                "ig": {
                                                    "post_type": [
                                                        1
                                                    ],
                                                    "share_as_feed": 1
                                                }
                                            }
                                        },
                                        "properties": {
                                            "prefix": {
                                                "type": "string",
                                                "description": "Text placed before the imported caption, separated by a blank line.",
                                                "example": "From our archive:"
                                            },
                                            "suffix": {
                                                "type": "string",
                                                "description": "Text placed after the imported caption, separated by a blank line.",
                                                "example": "Order online at acmecoffee.example"
                                            },
                                            "hashtags": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Hashtags appended after the suffix on one line, space separated. Each entry is trimmed and prefixed with `#` when it does not start with one.",
                                                "example": [
                                                    "coffee",
                                                    "#acme"
                                                ]
                                            },
                                            "first_comment": {
                                                "type": "string",
                                                "description": "First comment stored for Facebook pages, LinkedIn and Instagram feed posts unless a network-specific one is given.",
                                                "example": "Visit acmecoffee.example for opening hours."
                                            },
                                            "networks": {
                                                "type": "object",
                                                "properties": {
                                                    "fb": {
                                                        "type": "object",
                                                        "properties": {
                                                            "post_type": {
                                                                "type": "array",
                                                                "items": [],
                                                                "description": "Facebook post types as integers: `1` Feed, `2` Reel, `3` Story. Any combination of the three is accepted. Empty or missing means Feed.",
                                                                "example": [
                                                                    1,
                                                                    3
                                                                ]
                                                            },
                                                            "first_comment": {
                                                                "type": "string",
                                                                "description": "First comment for Facebook pages, overriding `customize.first_comment`.",
                                                                "example": "More photos on our page."
                                                            }
                                                        }
                                                    },
                                                    "ig": {
                                                        "type": "object",
                                                        "properties": {
                                                            "post_type": {
                                                                "type": "array",
                                                                "items": [],
                                                                "description": "Instagram post types as integers: `1` Feed, `2` Story, `3` Reel. Accepted combinations are a single type, `[1, 2]` (Feed and Story) and `[2, 3]` (Story and Reel); anything else falls back to Feed.",
                                                                "example": [
                                                                    1
                                                                ]
                                                            },
                                                            "share_as_feed": {
                                                                "type": "integer",
                                                                "description": "`1` to also share a Reel to the feed, `0` not to.",
                                                                "enum": [
                                                                    0,
                                                                    1
                                                                ],
                                                                "default": "0",
                                                                "example": 1
                                                            },
                                                            "trial_reel": {
                                                                "type": "string",
                                                                "description": "Publish Reels as trial reels. `MANUAL` keeps them as trials until you graduate them, `SS_PERFORMANCE` lets Instagram graduate them on performance. Empty string or omitted means no trial reel.",
                                                                "enum": [
                                                                    "",
                                                                    "MANUAL",
                                                                    "SS_PERFORMANCE"
                                                                ],
                                                                "example": ""
                                                            },
                                                            "first_comment": {
                                                                "type": "string",
                                                                "description": "First comment for Instagram feed posts, overriding `customize.first_comment`.",
                                                                "example": "Tag a friend who needs coffee."
                                                            }
                                                        }
                                                    },
                                                    "ln": {
                                                        "type": "object",
                                                        "properties": {
                                                            "first_comment": {
                                                                "type": "string",
                                                                "description": "First comment for LinkedIn, overriding `customize.first_comment`. LinkedIn has no other import option.",
                                                                "example": "Read the full story on our site."
                                                            }
                                                        }
                                                    },
                                                    "pi": {
                                                        "type": "object",
                                                        "properties": {
                                                            "title": {
                                                                "type": "string",
                                                                "description": "Pin title.",
                                                                "example": "New single origin"
                                                            },
                                                            "link": {
                                                                "type": "string",
                                                                "format": "uri",
                                                                "description": "Pin destination link.",
                                                                "example": "https://acmecoffee.example/beans"
                                                            }
                                                        }
                                                    },
                                                    "gmb": {
                                                        "type": "object",
                                                        "properties": {
                                                            "cta_type": {
                                                                "type": "integer",
                                                                "description": "Google Business call to action: `1` Learn more, `2` Sign up, `3` Buy, `4` Order online, `5` Book, `6` Call now, `8` Offer. Empty or omitted adds no button and ignores the other `gmb` keys.",
                                                                "enum": [
                                                                    1,
                                                                    2,
                                                                    3,
                                                                    4,
                                                                    5,
                                                                    6,
                                                                    8
                                                                ],
                                                                "example": 1
                                                            },
                                                            "link": {
                                                                "type": "string",
                                                                "format": "uri",
                                                                "description": "Button link for the web-link call to actions (types 1 to 5).",
                                                                "example": "https://acmecoffee.example/menu"
                                                            },
                                                            "offer_title": {
                                                                "type": "string",
                                                                "description": "Offer title. Read only when `cta_type` is 8.",
                                                                "example": "10% off this week"
                                                            },
                                                            "redeem_offer_link": {
                                                                "type": "string",
                                                                "format": "uri",
                                                                "description": "Link to redeem the offer. Read only when `cta_type` is 8.",
                                                                "example": "https://acmecoffee.example/offer"
                                                            },
                                                            "coupon_code": {
                                                                "type": "string",
                                                                "description": "Coupon code of the offer. Read only when `cta_type` is 8.",
                                                                "example": "BEANS10"
                                                            },
                                                            "start_date": {
                                                                "type": "string",
                                                                "format": "date",
                                                                "description": "First day of the offer, `YYYY-MM-DD`. Read only when `cta_type` is 8.",
                                                                "example": "2026-11-01"
                                                            },
                                                            "end_date": {
                                                                "type": "string",
                                                                "format": "date",
                                                                "description": "Last day of the offer, `YYYY-MM-DD`. Read only when `cta_type` is 8.",
                                                                "example": "2026-11-07"
                                                            },
                                                            "terms_and_conditions": {
                                                                "type": "string",
                                                                "description": "Offer terms. Read only when `cta_type` is 8.",
                                                                "example": "One per customer."
                                                            }
                                                        }
                                                    },
                                                    "tk": {
                                                        "type": "object",
                                                        "properties": {
                                                            "privacy_status": {
                                                                "type": "string",
                                                                "description": "TikTok audience. Applied to video posts only.",
                                                                "enum": [
                                                                    "PUBLIC_TO_EVERYONE",
                                                                    "MUTUAL_FOLLOW_FRIENDS",
                                                                    "SELF_ONLY"
                                                                ],
                                                                "default": "PUBLIC_TO_EVERYONE",
                                                                "example": "PUBLIC_TO_EVERYONE"
                                                            },
                                                            "comment_status": {
                                                                "type": "integer",
                                                                "description": "`1` allows comments on the TikTok video.",
                                                                "enum": [
                                                                    0,
                                                                    1
                                                                ],
                                                                "default": "0",
                                                                "example": 1
                                                            },
                                                            "duet_status": {
                                                                "type": "integer",
                                                                "description": "`1` allows duets.",
                                                                "enum": [
                                                                    0,
                                                                    1
                                                                ],
                                                                "default": "0",
                                                                "example": 0
                                                            },
                                                            "stitches_status": {
                                                                "type": "integer",
                                                                "description": "`1` allows stitches.",
                                                                "enum": [
                                                                    0,
                                                                    1
                                                                ],
                                                                "default": "0",
                                                                "example": 0
                                                            },
                                                            "promote_own_brand": {
                                                                "type": "integer",
                                                                "description": "`1` marks the video as promoting your own brand.",
                                                                "enum": [
                                                                    0,
                                                                    1
                                                                ],
                                                                "default": "0",
                                                                "example": 0
                                                            },
                                                            "promote_other_brand": {
                                                                "type": "integer",
                                                                "description": "`1` marks the video as branded content for a third party.",
                                                                "enum": [
                                                                    0,
                                                                    1
                                                                ],
                                                                "default": "0",
                                                                "example": 0
                                                            }
                                                        }
                                                    },
                                                    "yt": {
                                                        "type": "object",
                                                        "properties": {
                                                            "privacy_status": {
                                                                "type": "string",
                                                                "description": "YouTube visibility. Applied to video posts only.",
                                                                "enum": [
                                                                    "public",
                                                                    "private",
                                                                    "unlisted"
                                                                ],
                                                                "default": "public",
                                                                "example": "public"
                                                            },
                                                            "title": {
                                                                "type": "string",
                                                                "description": "Video title. When empty the imported post's own title is kept.",
                                                                "example": "Behind the bar at Acme"
                                                            },
                                                            "category": {
                                                                "type": "string",
                                                                "description": "YouTube category id, for example `22` for People and Blogs.",
                                                                "example": "22"
                                                            },
                                                            "tags": {
                                                                "type": "string",
                                                                "description": "Comma-separated video tags.",
                                                                "example": "coffee, barista"
                                                            },
                                                            "for_kids": {
                                                                "type": "integer",
                                                                "description": "`1` marks the video as made for kids.",
                                                                "enum": [
                                                                    0,
                                                                    1
                                                                ],
                                                                "default": "0",
                                                                "example": 0
                                                            },
                                                            "default_audio_language": {
                                                                "type": "string",
                                                                "description": "Audio language code, for example `en`.",
                                                                "example": "en"
                                                            },
                                                            "default_language": {
                                                                "type": "string",
                                                                "description": "Title and description language code, for example `en`.",
                                                                "example": "en"
                                                            },
                                                            "recording_date": {
                                                                "type": "string",
                                                                "format": "date",
                                                                "description": "Recording date, `YYYY-MM-DD`.",
                                                                "example": "2026-10-10"
                                                            },
                                                            "license": {
                                                                "type": "string",
                                                                "description": "`youtube` for the standard YouTube licence, `creativeCommon` for Creative Commons Attribution.",
                                                                "enum": [
                                                                    "youtube",
                                                                    "creativeCommon"
                                                                ],
                                                                "default": "youtube",
                                                                "example": "youtube"
                                                            },
                                                            "embeddable": {
                                                                "type": "integer",
                                                                "description": "`1` allows embedding the video on other sites.",
                                                                "enum": [
                                                                    0,
                                                                    1
                                                                ],
                                                                "default": "0",
                                                                "example": 1
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "account_id",
                                    "library_id",
                                    "ids"
                                ],
                                "example": {
                                    "account_id": "aB3dE5fG7h==",
                                    "library_id": "cD4eF6gH8i==",
                                    "ids": [
                                        48213,
                                        48201
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Imported`."
                                        },
                                        "library_id": {
                                            "type": "string",
                                            "description": "The `library_id` you sent."
                                        },
                                        "imported_count": {
                                            "type": "integer",
                                            "description": "Number of distinct ids in the batch."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Imported",
                                    "library_id": "cD4eF6gH8i==",
                                    "imported_count": 2
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (account_id or library_id is missing or does not decrypt to one id, or ids holds no positive integer.)\n\ncustomize must be a JSON object. (customize was sent but is neither an object nor a JSON string that decodes to one.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nThe import plugin covers Facebook pages, LinkedIn companies, Instagram business, Pinterest, Google Business, Threads and Bluesky accounts; this account is none of those. (The account is on a network the plugin does not import from.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account or the library does not belong to the workspace owner.)\n\nYour library content limit leaves room for N more post(s); M were sent. (The batch is larger than the owner's remaining library content allowance. Nothing is imported; N is the room left, M the number of ids sent.)\n\nYou have maximum allowed number of posts in your library. ... (The app hit the content limit while importing (for example after a concurrent import). The message contains an HTML upgrade link.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account is not attached to that workspace.)\n\nThis account is disconnected or not found; the plugin imports from active accounts only. (The account exists but is disconnected or paused.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library is not attached to that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app failed to import the batch. The status and message are the app's own when it sent any.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/import_posts_more": {
            "post": {
                "tags": [
                    "Import"
                ],
                "summary": "Pull the next page of older posts from the network into the import list.",
                "description": "Asks the network for the posts published before the oldest one already stored for `account_id` and adds them to the list `/api/import_posts` reads. The network is called during the request, so the call can take a few seconds and is limited to one fetch per account per minute, shared with `/api/import_refresh`. Read the result with `/api/import_posts` afterwards; this call returns no posts itself.\n\nNothing older may be left: The call answers 200 even when the network has no older posts to give; compare `total` in `/api/import_posts` before and after to see whether anything arrived.",
                "operationId": "import_posts_more",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted social account id from `/api/import_accounts`: a Facebook page, LinkedIn company, Instagram business, Pinterest, Google Business, Threads or Bluesky account.",
                                        "example": "aB3dE5fG7h=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "account_id"
                                ],
                                "example": {
                                    "account_id": "aB3dE5fG7h=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Older posts fetched; read them with import_posts.`"
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Older posts fetched; read them with import_posts."
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (account_id is missing or does not decrypt.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nThe import plugin covers Facebook pages, LinkedIn companies, Instagram business, Pinterest, Google Business, Threads and Bluesky accounts; this account is none of those. (The account is on another network (X, Facebook profiles and groups, LinkedIn profiles, TikTok, YouTube).)\n\nNo account found. (The app could not load the account.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account sits in another workspace.)\n\nThis account is disconnected or not found; the plugin imports from active accounts only. (The account is paused or needs reconnecting.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "One fetch per account per minute. Try again in N seconds. (A second fetch (this call or import_refresh) for the account inside the same clock minute. The Retry-After header carries the seconds.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The network returned no posts; the account may need reconnecting. (The app answered nothing usable, usually because the network refused the token.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/import_refresh": {
            "post": {
                "tags": [
                    "Import"
                ],
                "summary": "Pull the posts published since the last fetch, or clear the stored list and start over.",
                "description": "Asks the network for the posts of `account_id` published after the last fetch and adds them to the list `/api/import_posts` reads. With `reset=true` and `confirm=true` the stored list is cleared first and the newest posts are fetched again from scratch. One fetch per account per minute, shared with `/api/import_posts_more`. Read the result with `/api/import_posts`.\nAn account that was never fetched has no last fetch time; the refresh then behaves like `/api/import_posts_more` and pages back from the newest post.\n\nReset forgets what was imported: After a reset the stored list starts empty, so posts you already added to a library can show up again in `/api/import_posts` and be imported twice.",
                "operationId": "import_refresh",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted social account id from `/api/import_accounts`.",
                                        "example": "aB3dE5fG7h=="
                                    },
                                    "reset": {
                                        "type": "boolean",
                                        "description": "`true` deletes every stored post of the account and fetches again from the newest. Needs `confirm=true`.",
                                        "default": "false",
                                        "example": false
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be `true` when `reset` is true.",
                                        "example": false
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "account_id"
                                ],
                                "example": {
                                    "account_id": "aB3dE5fG7h=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`New posts fetched; read them with import_posts.`, or `Stored posts cleared and fetched again.` after a reset."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "New posts fetched; read them with import_posts."
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (account_id is missing or does not decrypt.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nThe import plugin covers Facebook pages, LinkedIn companies, Instagram business, Pinterest, Google Business, Threads and Bluesky accounts; this account is none of those. (The account is on another network.)\n\nSend confirm=true to clear the stored posts of the account and fetch again. (reset=true without confirm=true. Nothing is cleared.)\n\nThe stored posts could not be cleared. (reset: the app could not delete the stored list; a 500 when it sent no status.)\n\nNo account found. (The app could not load the account.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account sits in another workspace.)\n\nThis account is disconnected or not found; the plugin imports from active accounts only. (The account is paused or needs reconnecting.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "One fetch per account per minute. Try again in N seconds. (A second fetch (this call or import_posts_more) for the account inside the same clock minute. The Retry-After header carries the seconds.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The network returned no posts; the account may need reconnecting. (The app answered nothing usable, usually because the network refused the token.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/label_list": {
            "post": {
                "tags": [
                    "Post Labels"
                ],
                "summary": "List the account's labels with their colour, description and post count, plus the colour choices.",
                "description": "Returns every label of the workspace owner's account, sorted by name, with how many scheduled posts carry each one. The `colors` array lists the swatch names `/api/label_create` and `/api/label_update` accept.",
                "operationId": "label_list",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "colors": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Allowed colour names, always `blue, emerald, amber, rose, violet, cyan, slate, lime`."
                                            }
                                        },
                                        "labels": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Labels of the account, sorted by name. Empty when there are none.",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain integer label id. Use it as `id` on update and delete and in `label_ids` on assign."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Label name, unique within the account."
                                                    },
                                                    "color": {
                                                        "type": "string",
                                                        "description": "One of the `colors` values."
                                                    },
                                                    "description": {
                                                        "type": "string",
                                                        "description": "Free-text description, possibly empty."
                                                    },
                                                    "post_count": {
                                                        "type": "integer",
                                                        "description": "Number of scheduled posts carrying the label."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "colors": [
                                        "blue",
                                        "emerald",
                                        "amber",
                                        "rose",
                                        "violet",
                                        "cyan",
                                        "slate",
                                        "lime"
                                    ],
                                    "labels": [
                                        {
                                            "id": 31,
                                            "name": "Promo",
                                            "color": "rose",
                                            "description": "Sales and discount posts",
                                            "post_count": 14
                                        },
                                        {
                                            "id": 32,
                                            "name": "Tips",
                                            "color": "blue",
                                            "description": "",
                                            "post_count": 3
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to a workspace id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app could not read the labels. The status and message are the app's own when it sent any.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/label_create": {
            "post": {
                "tags": [
                    "Post Labels"
                ],
                "summary": "Create a label with a name, an optional description and a colour.",
                "description": "Adds a label to the workspace owner's account and returns it. Names are trimmed and must be unique within the account; colours are lower-cased and checked against the swatch list.\n\nAccount-wide: The label is created on the workspace owner's account. workspace_id only decides which owner that is; members of several workspaces of the same owner share one label set.",
                "operationId": "label_create",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "description": "Label name, 1 to 50 characters after trimming. Must not match an existing label of the account.",
                                        "example": "Promo"
                                    },
                                    "description": {
                                        "type": "string",
                                        "description": "Up to 120 characters after trimming.",
                                        "example": "Sales and discount posts"
                                    },
                                    "color": {
                                        "type": "string",
                                        "description": "Swatch name. Case-insensitive.",
                                        "enum": [
                                            "blue",
                                            "emerald",
                                            "amber",
                                            "rose",
                                            "violet",
                                            "cyan",
                                            "slate",
                                            "lime"
                                        ],
                                        "default": "blue",
                                        "example": "rose"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "name"
                                ],
                                "example": {
                                    "name": "Promo"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Label added`."
                                        },
                                        "label": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "Plain integer id of the new label."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Stored name."
                                                },
                                                "color": {
                                                    "type": "string",
                                                    "description": "Stored colour."
                                                },
                                                "description": {
                                                    "type": "string",
                                                    "description": "Stored description, empty string when none was sent."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Label added",
                                    "label": {
                                        "id": 31,
                                        "name": "Promo",
                                        "color": "rose",
                                        "description": "Sales and discount posts"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (name is missing or blank after trimming.)\n\nname must be 50 characters or fewer. (name is longer than 50 characters.)\n\ndescription must be 120 characters or fewer. (description is longer than 120 characters.)\n\ncolor must be one of blue, emerald, amber, rose, violet, cyan, slate, lime. (color is not a swatch name.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "A label with that name already exists. (Another label of the account has the same name.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app could not store the label. The status and message are the app's own when it sent any.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/label_update": {
            "post": {
                "tags": [
                    "Post Labels"
                ],
                "summary": "Rename a label or change its description or colour.",
                "description": "Changes one or more of `name`, `description` and `color` on a label of the workspace owner's account. Fields left out keep their current value. Returns the label as stored after the update.",
                "operationId": "label_update",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Plain integer label id from `/api/label_list`.",
                                        "example": 31
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "New name, 1 to 50 characters after trimming, unique within the account. Omit to keep the current name.",
                                        "example": "Promotions"
                                    },
                                    "description": {
                                        "type": "string",
                                        "description": "New description, up to 120 characters. Send an empty string to clear it; omit to keep it.",
                                        "example": "Sales, discounts and launches"
                                    },
                                    "color": {
                                        "type": "string",
                                        "description": "New swatch name. Case-insensitive. Omit to keep the current colour.",
                                        "enum": [
                                            "blue",
                                            "emerald",
                                            "amber",
                                            "rose",
                                            "violet",
                                            "cyan",
                                            "slate",
                                            "lime"
                                        ],
                                        "example": "amber"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 31
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Label updated`."
                                        },
                                        "label": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "Label id."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Name after the update."
                                                },
                                                "color": {
                                                    "type": "string",
                                                    "description": "Colour after the update."
                                                },
                                                "description": {
                                                    "type": "string",
                                                    "description": "Description after the update."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Label updated",
                                    "label": {
                                        "id": 31,
                                        "name": "Promotions",
                                        "color": "amber",
                                        "description": "Sales, discounts and launches"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or not a positive integer.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nname must be 50 characters or fewer. (name is longer than 50 characters.)\n\ndescription must be 120 characters or fewer. (description is longer than 120 characters.)\n\ncolor must be one of blue, emerald, amber, rose, violet, cyan, slate, lime. (color is not a swatch name.)\n\nname cannot be blank. (name was sent but is empty after trimming.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nLabel not found. (No label with that id belongs to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "A label with that name already exists. (Another label of the account already has the new name.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app could not store the change. The status and message are the app's own when it sent any.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/label_delete": {
            "post": {
                "tags": [
                    "Post Labels"
                ],
                "summary": "Delete a label and remove it from every post.",
                "description": "Deletes a label of the workspace owner's account. The label is taken off every scheduled post and library post that carried it; the posts themselves are untouched.\n\nNot reversible: Deleting a label removes it from the label report history as well. Rename it with `/api/label_update` if you only want a different name.",
                "operationId": "label_delete",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Plain integer label id from `/api/label_list`.",
                                        "example": 31
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 31
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Label deleted`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Label deleted"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or not a positive integer.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nLabel not found. (No label with that id belongs to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app could not delete the label. The status and message are the app's own when it sent any.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/label_assign": {
            "post": {
                "tags": [
                    "Post Labels"
                ],
                "summary": "Set, add or remove labels on one scheduled post or one library post.",
                "description": "Changes the labels on exactly one post: a scheduled post named by `post_id` (the same plain id `/api/post_status` takes, covering every account the post goes to) or a library post named by `content_id`. `action` decides how `label_ids` is applied: `set` replaces the current labels with the list, `add` adds the list to them, `remove` takes the list away. The answer is the list of labels now on the post, sorted by name.\n\nWritten directly: This endpoint writes the label rows itself and does not call the app, so there is no internal error path beyond the ones listed. Labels on a scheduled post apply to the post as a whole, not to one account's copy of it.\n\nClearing labels: To remove every label from a post send `action=set` with no `label_ids`. `remove` requires at least one id and silently ignores ids that were not on the post.\n\nWorkspace scope: With `workspace_id`, a `post_id` must go to at least one account of that workspace; otherwise the answer is 404 `Post not found.` Without it the post only has to belong to the workspace owner.",
                "operationId": "label_assign",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "post_id": {
                                        "type": "integer",
                                        "description": "Plain integer id of a scheduled post, as returned by `/api/post_content` and the queue endpoints. Required when `content_id` is not sent; never send both.",
                                        "example": 918273
                                    },
                                    "content_id": {
                                        "type": "string",
                                        "description": "Encrypted id of a library post, as returned by the library content endpoints. Required when `post_id` is not sent; never send both.",
                                        "example": "pQ7rS9tU1v=="
                                    },
                                    "label_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Plain integer label ids as a JSON array or a comma-separated string. Required for `add` and `remove`. With `set` an empty or missing list clears every label from the post.",
                                        "example": [
                                            31,
                                            32
                                        ]
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "`set` replaces, `add` appends, `remove` detaches. Case-insensitive.",
                                        "enum": [
                                            "set",
                                            "add",
                                            "remove"
                                        ],
                                        "default": "set",
                                        "example": "set"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "post_id": {
                                            "type": "integer",
                                            "description": "The scheduled post id you sent. Present only when `post_id` was used."
                                        },
                                        "content_id": {
                                            "type": "string",
                                            "description": "The library post id you sent. Present only when `content_id` was used."
                                        },
                                        "labels": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Labels now on the post, sorted by name. Empty when the post has none.",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Label id."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Label name."
                                                    },
                                                    "color": {
                                                        "type": "string",
                                                        "description": "Label colour."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "post_id": 918273,
                                    "labels": [
                                        {
                                            "id": 31,
                                            "name": "Promo",
                                            "color": "rose"
                                        },
                                        {
                                            "id": 32,
                                            "name": "Tips",
                                            "color": "blue"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Send exactly one of post_id or content_id. (Neither or both of post_id and content_id were sent, or the one sent is not a valid id.)\n\naction must be set, add or remove. (action is not one of the three values.)\n\nBad Request Please try again later (action is add or remove and label_ids holds no positive integer.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nPost not found. (post_id does not belong to a post of the workspace owner's accounts.)\n\nLibrary post not found. (content_id does not belong to a library post of the workspace owner.)\n\nlabel_ids 41, 42 are not labels of this account. (One or more label_ids are not labels of the workspace owner. The message lists the offending ids.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/hashtag_groups": {
            "post": {
                "tags": [
                    "Content Tools"
                ],
                "summary": "List, add, update, delete or copy the hashtag groups of a library.",
                "description": "A hashtag group turns a short `text` written in a post into its `hashtags` when the post is published from library `library_id`. `action` picks the operation:\n- `list` (default): the groups of the library.\n- `add`: a new group from `text` and `hashtags`.\n- `update`: changes group `tag_id`.\n- `delete`: removes group `tag_id` from the library; workspace owner only, needs `confirm=true`.\n- `copy`: copies every group of the library into `to_library_id`.\n\nA group copied into another library is shared between the two: an update changes it in both.\n\nCopied groups are shared: copy does not clone the groups: the destination library points at the same rows. Updating a group in either library changes it in both; delete only unlinks it from the library you name.",
                "operationId": "hashtag_groups",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted library id.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "What to do; see above.",
                                        "enum": [
                                            "list",
                                            "add",
                                            "update",
                                            "delete",
                                            "copy"
                                        ],
                                        "default": "list",
                                        "example": "list"
                                    },
                                    "text": {
                                        "type": "string",
                                        "description": "The text that triggers the group, 1 to 100 characters. Required when action is `add` or `update`.",
                                        "example": "promo"
                                    },
                                    "hashtags": {
                                        "type": "string",
                                        "description": "The hashtags the text becomes, 1 to 100 characters. Required when action is `add` or `update`.",
                                        "example": "#promo #sale"
                                    },
                                    "tag_id": {
                                        "type": "integer",
                                        "description": "Plain integer id of the group, from the list. Required when action is `update` or `delete`.",
                                        "example": 77
                                    },
                                    "to_library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library that receives the groups; another library of the owner. Required when action is `copy`.",
                                        "example": "bT4r8Vz1Kc=="
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be `true` when action is `delete`.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "library_id"
                                ],
                                "example": {
                                    "library_id": "nX2k9Qp7Lw=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success` for list; `Hashtag group added.`; `Hashtag group updated.`; `Hashtag group removed from the library.`; `Hashtag groups copied; the two libraries now share them.`"
                                        },
                                        "groups": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "tag_id": {
                                                        "type": "integer",
                                                        "description": "list: plain integer id of the group."
                                                    },
                                                    "text": {
                                                        "type": "string",
                                                        "description": "list: the trigger text."
                                                    },
                                                    "hashtags": {
                                                        "type": "string",
                                                        "description": "list: the hashtags it becomes."
                                                    }
                                                }
                                            }
                                        },
                                        "tag_id": {
                                            "type": "integer",
                                            "description": "add and update: the group's id."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "groups": [
                                        {
                                            "tag_id": 77,
                                            "text": "promo",
                                            "hashtags": "#promo #sale"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Send library_id and action as list, add, update, delete or copy. (library_id is missing or does not decrypt, or action is another word.)\n\ntext and hashtags are required, 100 characters at most each. (add or update with text or hashtags blank or longer than 100 characters.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nThe hashtag group could not be saved. (add or update refused by the app without a message (its own text, for example Sorry, there was an issue. Please try again later or contact support., replaces this one); a 500 when it sent no status.)\n\nSend confirm=true to remove the hashtag group from the library. (delete without confirm=true.)\n\nYou have no permission to delete ... (delete: the app refused the owner.)\n\nThe hashtag group could not be deleted. (delete refused by the app without a message; a 500 when it sent no status.)\n\nto_library_id must be another library. (copy without to_library_id, with one that does not decrypt, or with the same library.)\n\nThe hashtag groups could not be copied. (copy refused by the app without a message; a 500 when it sent no status.)\n\nThe hashtag groups could not be read. (list failed in the app without a message; a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (library_id or to_library_id does not belong to the workspace owner.)\n\nOnly the workspace owner can delete hashtag groups. (delete by a team member.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and a library sits in another workspace.)\n\ntag_id is not a hashtag group of this library. (update or delete with a tag_id that is missing or belongs to another library.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "A group with this text already exists in the library. (add or update with a text another group of the library already uses.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/tag_bags": {
            "post": {
                "tags": [
                    "Content Tools"
                ],
                "summary": "List, add, update or delete the owner's named hashtag sets.",
                "description": "A bag of tags is a named set of hashtags the workspace owner keeps to paste into posts. `action` picks the operation:\n- `list` (default): every bag.\n- `add`: a new bag from `name` and `hashtags`.\n- `update`: changes bag `bag_id`; `name` and `hashtags` left out keep their values.\n- `delete`: removes bag `bag_id`; workspace owner only, needs `confirm=true`.",
                "operationId": "tag_bags",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "What to do; see above.",
                                        "enum": [
                                            "list",
                                            "add",
                                            "update",
                                            "delete"
                                        ],
                                        "default": "list",
                                        "example": "list"
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "Bag name, 1 to 500 characters, unique for the owner. Required when action is `add`; optional on update.",
                                        "example": "Launch"
                                    },
                                    "hashtags": {
                                        "type": "string",
                                        "description": "The hashtags, 1 to 1000 characters. Required when action is `add`; optional on update.",
                                        "example": "#launch #new #acme"
                                    },
                                    "bag_id": {
                                        "type": "integer",
                                        "description": "Plain integer id of the bag, from the list. Required when action is `update` or `delete`.",
                                        "example": 12
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be `true` when action is `delete`.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success` for list; `Bag added.`; `Bag updated.`; `Bag deleted.`"
                                        },
                                        "bags": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "list: plain integer bag id."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "list: bag name."
                                                    },
                                                    "hashtags": {
                                                        "type": "string",
                                                        "description": "list: the hashtags."
                                                    }
                                                }
                                            }
                                        },
                                        "bag": {
                                            "type": "object",
                                            "description": "add and update: the saved bag with `id`, `name` and `hashtags`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Bag added.",
                                    "bag": {
                                        "id": 12,
                                        "name": "Launch",
                                        "hashtags": "#launch #new #acme"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "action must be list, add, update or delete. (action is another word.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nSend confirm=true to delete the bag. (delete without confirm=true.)\n\nYou have no permission to delete ... (delete: the app refused the owner.)\n\nThe bag could not be deleted. (delete refused by the app without a message; a 500 when it sent no status.)\n\nname (500 characters at most) and hashtags (1000 at most) are required. (add without name or hashtags, or either over its limit after merging with the bag's current values on update.)\n\nYou have no permission to update Bag of tags... (update: the app refused the caller.)\n\nThe bag could not be saved. (add or update refused by the app without a message; a 500 when it sent no status.)\n\nThe bags could not be read. (list failed in the app without a message; a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can delete bags of tags. (delete by a team member.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nBag not found. (update or delete with a bag_id that is not one of the owner's bags.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "A bag with this name already exists. (add or update with a name another bag already uses.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/watermark": {
            "post": {
                "tags": [
                    "Content Tools"
                ],
                "summary": "Read, set, delete or copy the watermark stamped on images, per account or for the workspace.",
                "description": "A watermark is stamped on every image at posting time. It is set on one social account (`scope=account`, the default) or on the workspace (`scope=workspace`, workspace owner only), in which case every account of the workspace without its own watermark inherits it. `action` picks the operation:\n- `get` (default): the current settings. For an account the answer also says whether it inherits the workspace watermark or opted out of it.\n- `set`: saves `image_url`, `opacity`, `size` and `position`; fields left out keep their current values, so a first set needs `image_url`. On the workspace, `force_account_ids` names accounts whose own watermark is replaced by the workspace one.\n- `delete`: removes the watermark and the stamped copies of images; needs `confirm=true`. On an account, `skip_inherit=true` also keeps it out of the workspace watermark.\n- `copy`: copies the watermark of `account_id` to `account_ids`; accounts only.\n\n`image_url` must be an image uploaded through `/api/media_upload_url` by the workspace owner.\n\nDelete removes stamped images: Deleting a watermark also deletes the watermarked copies of images made for queued posts; those posts go out with the plain image. Images already published are not affected.",
                "operationId": "watermark",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "scope": {
                                        "type": "string",
                                        "description": "`account` acts on one social account, `workspace` on the watermark every account of the workspace inherits.",
                                        "enum": [
                                            "account",
                                            "workspace"
                                        ],
                                        "default": "account",
                                        "example": "account"
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "What to do; see above. `copy` works with scope account only.",
                                        "enum": [
                                            "get",
                                            "set",
                                            "delete",
                                            "copy"
                                        ],
                                        "default": "get",
                                        "example": "get"
                                    },
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted social account id. Required when scope is `account`; for copy it is the source account.",
                                        "example": "aK3mZ8vQr1=="
                                    },
                                    "image_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "The watermark image, a URL from `/api/media_upload_url` under the owner's folder. Required when action is `set` and no watermark is saved yet.",
                                        "example": "https://cdn.example.com/u/1/watermark.png"
                                    },
                                    "opacity": {
                                        "type": "integer",
                                        "description": "set: 1 to 100 percent. Keeps the current value when omitted (50 on a first set).",
                                        "example": 50
                                    },
                                    "size": {
                                        "type": "integer",
                                        "description": "set: 5 to 100, the watermark's width as a percentage of the image. Keeps the current value when omitted (50 on a first set).",
                                        "example": 40
                                    },
                                    "position": {
                                        "type": "string",
                                        "description": "set: corner the watermark sits in. Keeps the current value when omitted (bottom_left on a first set).",
                                        "enum": [
                                            "top_left",
                                            "top_right",
                                            "bottom_left",
                                            "bottom_right"
                                        ],
                                        "example": "bottom_right"
                                    },
                                    "force_account_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "set with scope workspace: encrypted ids of accounts whose own watermark is replaced by the workspace one, at most 50. Accounts not listed keep their own.",
                                        "example": [
                                            "gB9xT4nWp2=="
                                        ]
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be `true` when action is `delete`.",
                                        "example": true
                                    },
                                    "skip_inherit": {
                                        "type": "boolean",
                                        "description": "delete with scope account: `true` also opts the account out of the workspace watermark.",
                                        "default": "false",
                                        "example": false
                                    },
                                    "account_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted ids of the accounts that receive the copy, at most 50. Required when action is `copy`.",
                                        "example": [
                                            "gB9xT4nWp2=="
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success` for get; `Watermark saved.`; `Watermark deleted.`; `Watermark copied.`"
                                        },
                                        "settings": {
                                            "type": "object",
                                            "description": "get and set: `image_url`, `opacity`, `size`, `position`; `null` on get when nothing is set."
                                        },
                                        "inherited_from_workspace": {
                                            "type": "object",
                                            "description": "get, scope account: the workspace watermark the account inherits, with `workspace.id`, `workspace.name`, `image_url`, `opacity`, `size`, `position`; `null` when none applies."
                                        },
                                        "opted_out": {
                                            "type": "boolean",
                                            "description": "get, scope account: `true` when the account was taken out of the workspace watermark and has none of its own."
                                        },
                                        "accounts": {
                                            "type": "object",
                                            "properties": {
                                                "total": {
                                                    "type": "integer",
                                                    "description": "get, scope workspace: accounts in the workspace."
                                                },
                                                "inheriting": {
                                                    "type": "integer",
                                                    "description": "get, scope workspace: accounts that take the workspace watermark."
                                                },
                                                "with_own_watermark": {
                                                    "type": "integer",
                                                    "description": "get, scope workspace: accounts that keep their own."
                                                }
                                            }
                                        },
                                        "propagated": {
                                            "type": "integer",
                                            "description": "set, scope workspace: accounts the watermark was applied to."
                                        },
                                        "overridden": {
                                            "type": "integer",
                                            "description": "set, scope workspace: accounts from force_account_ids whose own watermark was replaced."
                                        },
                                        "accounts_affected": {
                                            "type": "integer",
                                            "description": "delete, scope workspace: accounts that lost the inherited watermark."
                                        },
                                        "copied": {
                                            "type": "integer",
                                            "description": "copy: accounts that received the watermark."
                                        },
                                        "failed": {
                                            "type": "integer",
                                            "description": "copy: accounts the copy failed for."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "settings": null,
                                    "inherited_from_workspace": {
                                        "workspace": {
                                            "id": "wS7pQ2mN1x==",
                                            "name": "Main"
                                        },
                                        "image_url": "https://cdn.example.com/u/1/watermark.png",
                                        "opacity": 40,
                                        "size": 60,
                                        "position": "top_right"
                                    },
                                    "opted_out": false
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "scope must be account or workspace; action get, set, delete or copy. (scope or action is another word.)\n\ncopy works between accounts. (copy with scope workspace.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\naccount_id is required. (scope account without an account_id that decrypts.)\n\naccount_ids is required. (copy without account_ids, or one of them does not decrypt.)\n\nAt most 50 ids per call; N were sent. (account_ids or force_account_ids holds more than 50 ids.)\n\nThe watermark could not be copied. (copy refused by the app without a message; a 500 when it sent no status.)\n\nSend confirm=true to delete the watermark and its stamped images. (delete without confirm=true.)\n\nThe watermark could not be deleted. (delete refused by the app without a message; a 500 when it sent no status.)\n\nThe watermark could not be read. (get or set: the current settings could not be read from the app; a 500 when it sent no status.)\n\nimage_url must be an image uploaded through media_upload_url. (set without a saved image and no image_url, or with a URL outside the owner's upload folder.)\n\nposition must be top_left, top_right, bottom_left or bottom_right. (set with another position.)\n\nopacity must be 1 to 100 and size 5 to 100. (set with a value outside the range.)\n\nThe watermark could not be saved. (set refused by the app without a message (its own text, for example Watermark image required, replaces this one); a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (account_id, an id in account_ids or in force_account_ids does not belong to the workspace owner.)\n\nOnly the workspace owner can manage the workspace watermark. (scope workspace by a team member.)\n\nYou don't have permission to update this account's watermark. (get or set: the app refused the caller for the account (this workspace's watermark for scope workspace).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and an account sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The source account has no watermark. (copy from an account without one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/testimonial_templates": {
            "post": {
                "tags": [
                    "Content Tools"
                ],
                "summary": "List, add or delete the owner's testimonial template images.",
                "description": "Template images the owner lays testimonial text over when turning a review into a post. `action` picks the operation; every answer ends with the current list:\n- `list` (default).\n- `add`: stores `image_url`, an upload from `/api/media_upload_url`.\n- `delete`: removes template `template_id`; needs `confirm=true`.",
                "operationId": "testimonial_templates",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "What to do; see above.",
                                        "enum": [
                                            "list",
                                            "add",
                                            "delete"
                                        ],
                                        "default": "list",
                                        "example": "list"
                                    },
                                    "image_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "The template image, a URL from `/api/media_upload_url` under the owner's folder. Required when action is `add`.",
                                        "example": "https://cdn.example.com/u/1/testimonial-bg.png"
                                    },
                                    "template_id": {
                                        "type": "integer",
                                        "description": "Plain integer id of the template, from the list. Required when action is `delete`.",
                                        "example": 4
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be `true` when action is `delete`.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`; `Template added.`; `Template deleted.`"
                                        },
                                        "templates": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain integer template id."
                                                    },
                                                    "image_url": {
                                                        "type": "string",
                                                        "description": "The template image."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Template added.",
                                    "templates": [
                                        {
                                            "id": 4,
                                            "image_url": "https://cdn.example.com/u/1/testimonial-bg.png"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "action must be list, add or delete. (action is another word.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nimage_url must be an image uploaded through media_upload_url. (add with a URL outside the owner's upload folder.)\n\nThe template could not be saved. (add refused by the app without a message; a 500 when it sent no status.)\n\ntemplate_id is required. (delete without a positive template_id.)\n\nSend confirm=true to delete the template image. (delete without confirm=true.)\n\nThe template could not be deleted. (delete refused by the app without a message; a 500 when it sent no status.)\n\nThe templates could not be read. (The list failed in the app; a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nTemplate not found. (delete with a template_id that is not one of the owner's.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/shortener_accounts": {
            "post": {
                "tags": [
                    "Content Tools"
                ],
                "summary": "List the owner's URL shortener accounts and attach or detach social accounts to one of their domains.",
                "description": "Links in posts of a social account are shortened through the shortener (Bitly) account and domain the social account is attached to. `action` picks the operation; every answer carries the shorteners and the current attachments:\n- `list` (default).\n- `attach`: attaches `account_ids` to domain `domain_id` of shortener `shortener_id`. An account already attached elsewhere is moved.\n- `detach`: stops shortening for `account_ids`.\n\nConnecting a Bitly account itself is a browser flow in RecurPost; no token is returned here.",
                "operationId": "shortener_accounts",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "What to do; see above.",
                                        "enum": [
                                            "list",
                                            "attach",
                                            "detach"
                                        ],
                                        "default": "list",
                                        "example": "list"
                                    },
                                    "account_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted social account ids: one id, a comma-separated string or an array, at most 50. Required when action is `attach` or `detach`.",
                                        "example": [
                                            "aK3mZ8vQr1=="
                                        ]
                                    },
                                    "shortener_id": {
                                        "type": "integer",
                                        "description": "Plain integer id of the shortener account, from `shorteners[].id`. Required when action is `attach`.",
                                        "example": 3
                                    },
                                    "domain_id": {
                                        "type": "integer",
                                        "description": "Plain integer id of one of that shortener's domains, from `shorteners[].domains[].id`. Required when action is `attach`.",
                                        "example": 8
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`; `N account(s) attached.`; `N account(s) detached.`"
                                        },
                                        "shorteners": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain integer shortener account id."
                                                    },
                                                    "provider": {
                                                        "type": "string",
                                                        "description": "Always `bitly`."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Name of the shortener account."
                                                    },
                                                    "login": {
                                                        "type": "string",
                                                        "description": "Login at the provider."
                                                    },
                                                    "domains": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "object",
                                                            "description": "Its domains: `id`, `domain` and `shortener_id`."
                                                        }
                                                    }
                                                }
                                            }
                                        },
                                        "attached": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "account": {
                                                        "type": "object",
                                                        "description": "A social account that shortens links: `id`, `name`, `network`."
                                                    },
                                                    "shortener_id": {
                                                        "type": "integer",
                                                        "description": "The shortener it uses."
                                                    },
                                                    "domain_id": {
                                                        "type": "integer",
                                                        "description": "The domain it uses."
                                                    },
                                                    "domain": {
                                                        "type": "string",
                                                        "description": "The domain name."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "1 account(s) attached.",
                                    "shorteners": [
                                        {
                                            "id": 3,
                                            "provider": "bitly",
                                            "name": "Acme",
                                            "login": "acme",
                                            "domains": [
                                                {
                                                    "id": 8,
                                                    "domain": "bit.ly",
                                                    "shortener_id": 3
                                                }
                                            ]
                                        }
                                    ],
                                    "attached": [
                                        {
                                            "account": {
                                                "id": "aK3mZ8vQr1==",
                                                "name": "Acme",
                                                "network": "facebook"
                                            },
                                            "shortener_id": 3,
                                            "domain_id": 8,
                                            "domain": "bit.ly"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "action must be list, attach or detach. (action is another word.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nThe shortener accounts could not be read. (The shortener list failed in the app; a 500 when it sent no status.)\n\naccount_ids is required. (attach or detach without account_ids, or one of them does not decrypt.)\n\nAt most 50 ids per call; N were sent. (account_ids holds more than 50 ids.)\n\nThe accounts could not be attached. (attach refused by the app without a message; a 500 when it sent no status. detach answers The accounts could not be detached.)\n\nThe attached accounts could not be read. (The attachment list failed in the app; a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (An account in account_ids does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and an account sits in another workspace.)\n\nshortener_id and domain_id must come from this call's list, the domain belonging to the shortener. (attach with an unknown shortener or domain, or a domain of another shortener.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/catalog": {
            "post": {
                "tags": [
                    "Content Tools"
                ],
                "summary": "Create a product catalog on Meta for an Instagram account and manage its products.",
                "description": "The product catalog behind Instagram product tags (`in_product_tags` and `in_reel_product_tags` on `/api/post_content`; products are read with `/api/instagram_products`). Every call acts through Instagram business account `account_id` and is for the workspace owner only. `action` picks the operation:\n- `businesses` (default): the Meta businesses a catalog can be created under.\n- `create`: a new catalog named `name` under `business_id`.\n- `product_save`: adds a product to `catalog_id`, or changes product `product_id`; send one of the two.\n- `product_delete`: removes product `product_id` from Meta; needs `confirm=true`.\n\nMeta's own refusals come back as 400 with Meta's reason; an account whose token Meta no longer accepts answers 409 with `reconnect_required`.\n\nChanges happen on Meta: Catalogs and products live in Meta's Commerce Manager, not in RecurPost. A new catalog must be connected to the Instagram shop in Commerce Manager before its products can be tagged, and Meta reviews new products for a few minutes before `/api/instagram_products` lists them.",
                "operationId": "catalog",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the Instagram business account.",
                                        "example": "aK3mZ8vQr1=="
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "What to do; see above.",
                                        "enum": [
                                            "businesses",
                                            "create",
                                            "product_save",
                                            "product_delete"
                                        ],
                                        "default": "businesses",
                                        "example": "businesses"
                                    },
                                    "business_id": {
                                        "type": "string",
                                        "description": "Meta business id from the businesses list. Required when action is `create`.",
                                        "example": "555000111222333"
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "Catalog name, 1 to 100 characters, required when action is `create`. For product_save: the product name, 1 to 150 characters, required for a new product.",
                                        "example": "Summer collection"
                                    },
                                    "catalog_id": {
                                        "type": "string",
                                        "description": "Meta catalog id to add a product to. product_save: send this for a new product, or product_id for an existing one, not both.",
                                        "example": "777000111222333"
                                    },
                                    "product_id": {
                                        "type": "string",
                                        "description": "Meta product id, from `/api/instagram_products`. Required when action is `product_delete`; product_save: send it to change the product.",
                                        "example": "901000111222333"
                                    },
                                    "price": {
                                        "type": "string",
                                        "description": "product_save: the price as a number in the currency's units, for example `12.50`. Required for a new product.",
                                        "example": "12.50"
                                    },
                                    "currency": {
                                        "type": "string",
                                        "description": "product_save: ISO currency code. Required for a new product.",
                                        "example": "USD"
                                    },
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "product_save: the product page, starting with http:// or https://.",
                                        "example": "https://shop.example.com/hat"
                                    },
                                    "image_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "product_save: the product image, starting with http:// or https://.",
                                        "example": "https://shop.example.com/img/hat.jpg"
                                    },
                                    "description": {
                                        "type": "string",
                                        "description": "product_save: up to 5000 characters.",
                                        "example": "Wide-brim straw hat."
                                    },
                                    "availability": {
                                        "type": "string",
                                        "description": "product_save: Meta availability value, for example `in stock` or `out of stock`.",
                                        "example": "in stock"
                                    },
                                    "brand": {
                                        "type": "string",
                                        "description": "product_save: brand name.",
                                        "example": "Acme"
                                    },
                                    "retailer_id": {
                                        "type": "string",
                                        "description": "product_save: your own SKU or id for the product.",
                                        "example": "HAT-001"
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be `true` when action is `product_delete`.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "account_id"
                                ],
                                "example": {
                                    "account_id": "aK3mZ8vQr1=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success` for businesses; `Catalog created; connect it to the Instagram shop in Commerce Manager before tagging products.`; `Product added. Meta reviews new products before they can be tagged, which usually takes a few minutes.` or `Product updated.`; `Product deleted.`"
                                        },
                                        "businesses": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "businesses: Meta business id."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "businesses: business name."
                                                    }
                                                }
                                            }
                                        },
                                        "catalog_id": {
                                            "type": "string",
                                            "description": "create: the new catalog's Meta id."
                                        },
                                        "product_id": {
                                            "type": "string",
                                            "description": "product_save: the product's Meta id."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Product added. Meta reviews new products before they can be tagged, which usually takes a few minutes.",
                                    "product_id": "901000111222333"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "action must be businesses, create, product_save or product_delete. (action is another word.)\n\naccount_id is required. (account_id is missing or does not decrypt.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\nbusiness_id and name (100 characters at most) are required. (create without a numeric business_id or a name of 1 to 100 characters.)\n\nWe couldn't create the catalog. (Meta refused the catalog; Meta's reason follows the sentence. Other app checks answer 400 the same way: Please choose the business this catalog belongs to., Please enter a catalog name., Catalog name can be up to 100 characters.)\n\nproduct_id is required. (product_delete without a numeric product_id.)\n\nSend confirm=true to delete the product from the catalog on Meta. (product_delete without confirm=true.)\n\nWe couldn't delete this product. (Meta refused the deletion; Meta's reason follows the sentence.)\n\nSend catalog_id for a new product or product_id to change one. (product_save with neither or both.)\n\nPlease enter a product name. (product_save for a new product without name. The other field checks answer 400 the same way: Product name can be up to 150 characters., Please enter a valid price., Please choose a currency., Please enter a valid product link starting with http:// or https://., Please enter a valid image link starting with http:// or https://., Description can be up to 5000 characters.)\n\nWe couldn't add this product. (Meta refused the product; Meta's reason follows the sentence. On a change the text is We couldn't update this product.)\n\nWe couldn't load the catalogs for this profile. (businesses: Meta refused the request; Meta's reason follows the sentence.)\n\nMeta did not accept the request. (The app refused without a message; a 500 when it sent no status.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can manage the product catalog. (The caller is a team member.)\n\nSorry, there was an issue. Please try again later or contact support. (account_id does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "(the app's reconnect message) (Meta no longer accepts the account's token; the body carries `reconnect_required: true`. Reconnect the account in RecurPost.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/approval_list": {
            "post": {
                "tags": [
                    "Approvals"
                ],
                "summary": "List library posts in the approval flow: waiting on you, sent by you, or rejected.",
                "description": "Returns library posts in the approval flow for one scope: `to_review` (sent to you and still waiting, the default), `submitted` (sent by you and still waiting) or `rejected` (sent by you and turned down, with the reviewers' comments). Narrow to one library with `library_id`.\nEach item carries the post's original content, the library it belongs to, who submitted it and when, every reviewer with their decision, and the comment count. The app returns the full set; this endpoint pages it for you, so `total` is the size of the whole scope.\n\nCounts are scope-independent: `counts` always holds all four numbers for the caller in the workspace, whichever scope was asked for; only `items` and `total` follow the scope.\n\nLarger pages than elsewhere: This list allows `per_page` up to 100 rather than the usual 50.",
                "operationId": "approval_list",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "scope": {
                                        "type": "string",
                                        "description": "`to_review`: waiting for your decision. `submitted`: yours, still waiting on others. `rejected`: yours, turned down, with the reviewers' comments. `rejected_by_you`: posts of others you turned down as a reviewer, with the comments. Case-insensitive.",
                                        "enum": [
                                            "to_review",
                                            "submitted",
                                            "rejected",
                                            "rejected_by_you"
                                        ],
                                        "default": "to_review",
                                        "example": "to_review"
                                    },
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted library id from `/api/library_list`; only posts of that library are returned. The library must belong to the workspace owner.",
                                        "example": "kL8mN2oP4q=="
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Page number, starting at 1.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "per_page": {
                                        "type": "integer",
                                        "description": "Items per page, 1 to 100.",
                                        "default": "20",
                                        "example": 20
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "scope": {
                                            "type": "string",
                                            "description": "Scope used, in lower case."
                                        },
                                        "page": {
                                            "type": "integer",
                                            "description": "Page returned."
                                        },
                                        "per_page": {
                                            "type": "integer",
                                            "description": "Page size used, after capping at 100."
                                        },
                                        "total": {
                                            "type": "integer",
                                            "description": "Number of posts in the scope across all pages."
                                        },
                                        "counts": {
                                            "type": "object",
                                            "properties": {
                                                "to_review": {
                                                    "type": "integer",
                                                    "description": "Posts waiting for your decision."
                                                },
                                                "submitted": {
                                                    "type": "integer",
                                                    "description": "Your posts still waiting on others."
                                                },
                                                "rejected": {
                                                    "type": "integer",
                                                    "description": "Your posts that were rejected."
                                                },
                                                "rejected_by_you": {
                                                    "type": "integer",
                                                    "description": "Posts of others you rejected."
                                                }
                                            }
                                        },
                                        "items": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Posts on this page.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted library post id. Pass it as `id` to `/api/approval_decide`."
                                                    },
                                                    "message": {
                                                        "type": "string",
                                                        "description": "Post text of the original tab."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Link title when the post carries a link, else blank."
                                                    },
                                                    "description": {
                                                        "type": "string",
                                                        "description": "Link description, else blank."
                                                    },
                                                    "url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Link URL, else blank."
                                                    },
                                                    "image_url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "First image, else the link preview image, else the video thumbnail, else blank."
                                                    },
                                                    "images": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "array",
                                                            "items": [],
                                                            "description": "Image URLs attached to the post."
                                                        }
                                                    },
                                                    "video_url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Video URL, else blank."
                                                    },
                                                    "live_date": {
                                                        "type": "string",
                                                        "format": "date",
                                                        "description": "Date the post may start publishing, `YYYY-MM-DD`, blank when unrestricted."
                                                    },
                                                    "expire_date": {
                                                        "type": "string",
                                                        "format": "date",
                                                        "description": "Blank for approval items; the app does not return the expiry here."
                                                    },
                                                    "variations": {
                                                        "type": "integer",
                                                        "description": "Always 1 for approval items."
                                                    },
                                                    "created_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "Blank for approval items; use `submitted_at`."
                                                    },
                                                    "library": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "description": "Encrypted id of the library the post was added to."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Library name."
                                                            }
                                                        }
                                                    },
                                                    "submitted_by": {
                                                        "type": "string",
                                                        "description": "Name of the member who added the post."
                                                    },
                                                    "submitted_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When the post was added, as stored by the app (UTC)."
                                                    },
                                                    "approvers": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "array",
                                                            "items": [],
                                                            "description": "Everyone the post was sent to for review.",
                                                            "properties": {
                                                                "id": {
                                                                    "type": "string",
                                                                    "description": "Encrypted user id of the reviewer."
                                                                },
                                                                "name": {
                                                                    "type": "string",
                                                                    "description": "Reviewer's name."
                                                                },
                                                                "decision": {
                                                                    "type": "string",
                                                                    "description": "`pending`, `approved` or `rejected`."
                                                                }
                                                            }
                                                        }
                                                    },
                                                    "comments_count": {
                                                        "type": "integer",
                                                        "description": "Number of comments on the post; present on the rejected and rejected_by_you scopes."
                                                    },
                                                    "comments": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "array",
                                                            "items": [],
                                                            "description": "Only in scope `rejected`: the reviewers' rejection messages.",
                                                            "properties": {
                                                                "by": {
                                                                    "type": "string",
                                                                    "description": "Name of the reviewer who rejected."
                                                                },
                                                                "text": {
                                                                    "type": "string",
                                                                    "description": "Rejection message."
                                                                },
                                                                "at": {
                                                                    "type": "string",
                                                                    "format": "date-time",
                                                                    "description": "When it was written, as stored by the app (UTC)."
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "scope": "to_review",
                                    "page": 1,
                                    "per_page": 20,
                                    "total": 2,
                                    "counts": {
                                        "to_review": 2,
                                        "submitted": 1,
                                        "rejected": 0,
                                        "rejected_by_you": 4
                                    },
                                    "items": [
                                        {
                                            "id": "sP9cM3xY1z==",
                                            "message": "Five ways to keep your evergreen content fresh",
                                            "title": "",
                                            "description": "",
                                            "url": "",
                                            "image_url": "https://cdn.recurpost.com/media/12/fresh.jpg",
                                            "images": [
                                                "https://cdn.recurpost.com/media/12/fresh.jpg"
                                            ],
                                            "video_url": "",
                                            "live_date": "",
                                            "expire_date": "",
                                            "variations": 1,
                                            "created_at": "",
                                            "library": {
                                                "id": "kL8mN2oP4q==",
                                                "name": "Evergreen tips"
                                            },
                                            "submitted_by": "Au Thor",
                                            "submitted_at": "2026-10-01 10:00:00",
                                            "approvers": [
                                                {
                                                    "id": "Jd3xP0wQ1A==",
                                                    "name": "Jane Doe",
                                                    "decision": "pending"
                                                },
                                                {
                                                    "id": "Sl7mN2vB4Q==",
                                                    "name": "Sam Lee",
                                                    "decision": "approved"
                                                }
                                            ],
                                            "comments_count": 2
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "scope must be to_review, submitted, rejected or rejected_by_you. (scope is another word.)\n\nlibrary_id is not a valid library id. (library_id was sent but does not decrypt to one library id.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (library_id names a library that does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nThis library is not part of the selected workspace. (workspace_id was given and the library sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The list failed inside the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/approval_decide": {
            "post": {
                "tags": [
                    "Approvals"
                ],
                "summary": "Approve a waiting library post into its library, or reject it with a message for the author.",
                "description": "Records your decision on a post that is waiting for approval. You must be one of the post's reviewers and the post must still be waiting. `approve` moves the post into its library's rotation; `reject` turns it down and stores your `message` for the author, who sees it under scope `rejected` of `/api/approval_list`.\n\nDecisions are final: Once approved or rejected, the post cannot be decided again through the API; a second call answers 409. The author comments on a rejected post with `/api/approval_comment` and sends it back with `/api/approval_resend`; the content itself is edited in RecurPost.\n\nApproval counts against the plan: An approved post joins the library like any other post, so the owner's library post limit applies at the moment of approval, not when the author submitted it.",
                "operationId": "approval_decide",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted library post id from `/api/approval_list` (scope `to_review`).",
                                        "example": "sP9cM3xY1z=="
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "`approve` or `reject`. Case-insensitive.",
                                        "enum": [
                                            "approve",
                                            "reject"
                                        ],
                                        "example": "approve"
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "Required when `action` is `reject`: what the author should change. Ignored on approve.",
                                        "example": "Please shorten the caption and fix the typo in the first line."
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id",
                                    "action"
                                ],
                                "example": {
                                    "id": "sP9cM3xY1z==",
                                    "action": "approve"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Post approved` or `Post rejected`."
                                        },
                                        "id": {
                                            "type": "string",
                                            "description": "The encrypted post id you sent."
                                        },
                                        "decision": {
                                            "type": "string",
                                            "description": "`approved` or `rejected`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Post approved",
                                    "id": "sP9cM3xY1z==",
                                    "decision": "approved"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or does not decrypt to one post id, or action is missing.)\n\naction must be approve or reject. (action is another word.)\n\nA message for the author is required to reject. (action is reject and message is blank.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The post does not belong to the workspace owner.)\n\nYou are not one of this post's reviewers. (The post waits on other reviewers, not on you.)\n\nYou have maximum allowed number of posts in your library. Please ... (Approving would exceed the library post limit of the owner's plan. The full text names the upgrade option.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nThis post is not in the approval flow. (The post was never sent for approval.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This post is no longer waiting for approval; it was approved already. (A decision was already recorded. The last word is `approved` or `rejected` accordingly.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The decision failed inside the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/approval_comment": {
            "post": {
                "tags": [
                    "Approvals"
                ],
                "summary": "Add a comment to the thread of a rejected post.",
                "description": "Writes a comment on a post that was rejected in the approval flow, for the author and the reviewers to talk the changes through. Only the post's author and its reviewers may write, and only while the post is rejected; a waiting or approved post takes no comments. The answer is the whole thread after the add, in the order it was written.\n\nWhere the thread shows: The same comments appear under `items[].comments` of `/api/approval_list` with scope `rejected`, and in the app's Rejected tab. Use `/api/approval_resend` once the post has been edited.",
                "operationId": "approval_comment",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "content_id": {
                                        "type": "string",
                                        "description": "Encrypted library post id from `items[].id` of `/api/approval_list` (scope `rejected`).",
                                        "example": "sP9cM3xY1z=="
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "The comment, 1 to 2000 characters. Surrounding spaces are trimmed.",
                                        "example": "Fixed the typo and shortened the caption."
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "content_id",
                                    "message"
                                ],
                                "example": {
                                    "content_id": "sP9cM3xY1z==",
                                    "message": "Fixed the typo and shortened the caption."
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Comment added.`"
                                        },
                                        "comments": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "by": {
                                                        "type": "string",
                                                        "description": "Name of the person who wrote the comment."
                                                    },
                                                    "text": {
                                                        "type": "string",
                                                        "description": "The comment."
                                                    },
                                                    "at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When it was written, UTC."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Comment added.",
                                    "comments": [
                                        {
                                            "by": "Jane Doe",
                                            "text": "Too long, please cut the second paragraph.",
                                            "at": "2026-10-20 10:00:00"
                                        },
                                        {
                                            "by": "Au Thor",
                                            "text": "Fixed the typo and shortened the caption.",
                                            "at": "2026-10-22 09:15:00"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\ncontent_id is required. (content_id is missing or does not decrypt to one post id.)\n\nmessage must be 1 to 2000 characters. (message is blank or too long.)\n\nSomething went wrong (The app could not store the comment; its own text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The post does not belong to the workspace owner.)\n\nYou are neither the author nor a reviewer of this post. (The post is someone else's and you were not asked to review it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nThis post is not in the approval flow. (The post was never sent for approval.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Comments go on rejected posts only. (The post is still waiting or was approved.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/approval_edit": {
            "post": {
                "tags": [
                    "Approvals"
                ],
                "summary": "Rewrite a post that is waiting for approval or was rejected, as its author or a reviewer; a reviewer may approve it in the same call.",
                "description": "Replaces the content of a post in the approval flow, waiting or rejected, with the same fields `/api/library_content_update` takes: the whole post is rewritten, so send every field you want kept. The caller must be the post's author or one of its reviewers. With `approve=true` a reviewer saves and approves in one step, which puts the post into the library's rotation and counts against the owner's library post limit. Without it the post stays where it is in the flow: a rejected post goes back to its reviewers with `/api/approval_resend`.\n\nWhole post: As with `/api/library_content_update`, fields left out are cleared, not kept. Read the post first with `/api/library_content`.\n\nPer-network media: A network can post media of its own: `<prefix>_image_url` and `<prefix>_video_url` (`fb_`, `tw_`, `ln_`, `in_`, `gmb_`, `pi_`, `yt_`, `tk_`, `th_`, `bs_`) replace `image_url` / `video_url` on that network only and mark its tab as customised. Each network keeps its own cap (Facebook 15, Twitter/X 4, LinkedIn 20, Instagram 10 in all, Google Business 1, Pinterest 1, TikTok 10, Threads 20 in all, Bluesky 4); only Instagram and Threads combine images with a video, ordered by `in_media_order` / `th_media_order`; YouTube takes `yt_video_url` only. A URL named by several networks is downloaded once. Covers (`fb_thumb` and the others) apply to whichever video that network ends up with; `in_image_tags` and `in_product_tags` positions count in `in_image_url` when Instagram has its own images. Removing all media from one network is not possible: an empty override answers 400.",
                "operationId": "approval_edit",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "content_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the post, from `/api/approval_list`.",
                                        "example": "cT5uV7wX=="
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "New post text. `\\r\\n` is normalised to `\\n`.",
                                        "example": "Updated: our latest product is now 20% off! https://example.com/product"
                                    },
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link to share with the post. On a text post the page's title, description and image are fetched and saved as the link preview; when omitted, the first link found in `message` is used instead. On a Pinterest account the value becomes the pin's destination link. `http://` is prepended when the scheme is missing. The host must be a public address.",
                                        "example": "https://example.com/summer-sale"
                                    },
                                    "image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Image URLs, in display order. Send a JSON array (or repeat `image_url[]` in form encoding); a single string is accepted as a one-item list. At most 20 images. Each URL must be a publicly reachable http or https URL and answer an image content type. URLs returned by `/api/media_upload_url` are used as they are; every other URL is copied to RecurPost storage unless `host_images_on_recurpost` is off. Ignored when `video_url` is also sent.",
                                        "example": [
                                            "https://example.com/sale1.jpg",
                                            "https://example.com/sale2.jpg"
                                        ]
                                    },
                                    "video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A public mp4 or mov URL (Google Drive share links are accepted and resolved to the download URL). The file is downloaded and stored on RecurPost storage, so the call takes as long as the download; a URL from `/api/media_upload_url` skips the download. Needs a paid plan. Files are limited to 2 GB.",
                                        "example": "https://example.com/promo.mp4"
                                    },
                                    "host_images_on_recurpost": {
                                        "type": "boolean",
                                        "description": "Copy images and custom thumbnails to RecurPost storage (the default). Send `false`, `0` or the form string `\"false\"` to keep your own URLs instead; they must then stay reachable until every post using them has been published.",
                                        "default": "true",
                                        "example": true
                                    },
                                    "alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text per image, in `image_url` order; a single string applies to the first image. At most 1000 characters each. Saved on the Facebook, Twitter/X, LinkedIn, Pinterest, Threads and Bluesky tabs; Instagram does not take alt text here.",
                                        "example": [
                                            "Two models in summer outfits",
                                            "Store front with sale banner"
                                        ]
                                    },
                                    "fb_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Facebook accounts instead of `image_url`, same rules and hosting as `image_url`. At most 15 images on Facebook. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `fb_video_url`.",
                                        "example": [
                                            "https://example.com/fb-square.jpg"
                                        ]
                                    },
                                    "fb_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Facebook accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `fb_image_url`.",
                                        "example": "https://example.com/fb-clip.mp4"
                                    },
                                    "fb_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `fb_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "tw_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Twitter/X accounts instead of `image_url`, same rules and hosting as `image_url`. At most 4 images on Twitter/X. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `tw_video_url`.",
                                        "example": [
                                            "https://example.com/tw-square.jpg"
                                        ]
                                    },
                                    "tw_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Twitter/X accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `tw_image_url`.",
                                        "example": "https://example.com/tw-clip.mp4"
                                    },
                                    "tw_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `tw_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "ln_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for LinkedIn accounts instead of `image_url`, same rules and hosting as `image_url`. At most 20 images on LinkedIn. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `ln_video_url`.",
                                        "example": [
                                            "https://example.com/ln-square.jpg"
                                        ]
                                    },
                                    "ln_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for LinkedIn accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `ln_image_url`.",
                                        "example": "https://example.com/ln-clip.mp4"
                                    },
                                    "ln_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `ln_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "in_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Instagram accounts instead of `image_url`, same rules and hosting as `image_url`. At most 10 media in all, images and video together on Instagram. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. May be combined with `in_video_url` into a carousel; `in_media_order` sets the order.",
                                        "example": [
                                            "https://example.com/in-square.jpg"
                                        ]
                                    },
                                    "in_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Instagram accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. May be combined with `in_image_url` into a carousel.",
                                        "example": "https://example.com/in-clip.mp4"
                                    },
                                    "in_media_order": {
                                        "type": "array",
                                        "items": [],
                                        "description": "The order of Instagram's own media as a list of the URLs given in `in_image_url` and `in_video_url`. Media left out of the list follow, video first. Only read when both are sent. Any other URL answers 400.",
                                        "example": [
                                            "https://example.com/in-clip.mp4",
                                            "https://example.com/in-square.jpg"
                                        ]
                                    },
                                    "gmb_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Google Business accounts instead of `image_url`, same rules and hosting as `image_url`. At most 1 image on Google Business. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `gmb_video_url`.",
                                        "example": [
                                            "https://example.com/gmb-square.jpg"
                                        ]
                                    },
                                    "gmb_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Google Business accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `gmb_image_url`.",
                                        "example": "https://example.com/gmb-clip.mp4"
                                    },
                                    "pi_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Pinterest accounts instead of `image_url`, same rules and hosting as `image_url`. At most 1 image on Pinterest. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `pi_video_url`.",
                                        "example": [
                                            "https://example.com/pi-square.jpg"
                                        ]
                                    },
                                    "pi_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Pinterest accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `pi_image_url`.",
                                        "example": "https://example.com/pi-clip.mp4"
                                    },
                                    "pi_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `pi_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "yt_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for YouTube accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. YouTube takes a video only, so there is no `yt_image_url`.",
                                        "example": "https://example.com/yt-clip.mp4"
                                    },
                                    "tk_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for TikTok accounts instead of `image_url`, same rules and hosting as `image_url`. At most 10 images on TikTok. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `tk_video_url`.",
                                        "example": [
                                            "https://example.com/tk-square.jpg"
                                        ]
                                    },
                                    "tk_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for TikTok accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `tk_image_url`.",
                                        "example": "https://example.com/tk-clip.mp4"
                                    },
                                    "th_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Threads accounts instead of `image_url`, same rules and hosting as `image_url`. At most 20 media in all, images and video together on Threads. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. May be combined with `th_video_url` into a carousel; `th_media_order` sets the order.",
                                        "example": [
                                            "https://example.com/th-square.jpg"
                                        ]
                                    },
                                    "th_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Threads accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. May be combined with `th_image_url` into a carousel.",
                                        "example": "https://example.com/th-clip.mp4"
                                    },
                                    "th_media_order": {
                                        "type": "array",
                                        "items": [],
                                        "description": "The order of Threads's own media as a list of the URLs given in `th_image_url` and `th_video_url`. Media left out of the list follow, video first. Only read when both are sent. Any other URL answers 400.",
                                        "example": [
                                            "https://example.com/th-clip.mp4",
                                            "https://example.com/th-square.jpg"
                                        ]
                                    },
                                    "th_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `th_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "bs_image_url": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Images for Bluesky accounts instead of `image_url`, same rules and hosting as `image_url`. At most 4 images on Bluesky. Replaces that network's whole media set and marks its tab as customised; the other networks keep the shared media. Cannot be combined with `bs_video_url`.",
                                        "example": [
                                            "https://example.com/bs-square.jpg"
                                        ]
                                    },
                                    "bs_video_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A video for Bluesky accounts instead of `video_url`, same rules and hosting as `video_url` (mp4 or mov, paid plan). Replaces that network's whole media set and marks its tab as customised. Cannot be combined with `bs_image_url`.",
                                        "example": "https://example.com/bs-clip.mp4"
                                    },
                                    "bs_alt_text": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Alternative text for the `bs_image_url` images, in that order; at most 1000 characters each. The shared `alt_text` is not applied to a network that has its own images.",
                                        "example": [
                                            "Square crop of the sale banner"
                                        ]
                                    },
                                    "fb_message": {
                                        "type": "string",
                                        "description": "Text for Facebook accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #facebook"
                                    },
                                    "tw_message": {
                                        "type": "string",
                                        "description": "Text for Twitter/X accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #twitter"
                                    },
                                    "ln_message": {
                                        "type": "string",
                                        "description": "Text for LinkedIn accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #linkedin"
                                    },
                                    "in_message": {
                                        "type": "string",
                                        "description": "Text for Instagram accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #instagram"
                                    },
                                    "gmb_message": {
                                        "type": "string",
                                        "description": "Text for Google Business accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #googlebusiness"
                                    },
                                    "pi_message": {
                                        "type": "string",
                                        "description": "Text for Pinterest accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #pinterest"
                                    },
                                    "yt_message": {
                                        "type": "string",
                                        "description": "Text for YouTube accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview. On YouTube this is the video description.",
                                        "example": "Summer sale is here! #youtube"
                                    },
                                    "tk_message": {
                                        "type": "string",
                                        "description": "Text for TikTok accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #tiktok"
                                    },
                                    "th_message": {
                                        "type": "string",
                                        "description": "Text for Threads accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #threads"
                                    },
                                    "bs_message": {
                                        "type": "string",
                                        "description": "Text for Bluesky accounts when it should differ from `message`. On a text-only post the first link in this text becomes that network's link preview.",
                                        "example": "Summer sale is here! #bluesky"
                                    },
                                    "first_comment": {
                                        "type": "string",
                                        "description": "First comment posted right after the post, commonly hashtags. Applied on Facebook Pages, LinkedIn and Instagram feed posts unless a network-specific first comment is given.",
                                        "example": "#summer #sale #deals"
                                    },
                                    "fb_first_comment": {
                                        "type": "string",
                                        "description": "Facebook first comment; overrides `first_comment` on Facebook.",
                                        "example": "#facebook #summersale"
                                    },
                                    "fb_mentions": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Facebook pages to mention, at most 10: page ids from `/api/mention_search`, as a list of ids or of `{page_id, name}` objects. Write each page in the text as `@<page id>`; the publisher turns it into the page's mention on Facebook pages.",
                                        "example": [
                                            {
                                                "page_id": "108296975869040",
                                                "name": "Acme"
                                            }
                                        ]
                                    },
                                    "fb_background_id": {
                                        "type": "string",
                                        "description": "Facebook text background for a post without `image_url` or `video_url`: an id from `/api/facebook_backgrounds` (letters, digits, underscore or dash, up to 64 characters). Applied on Facebook pages only.",
                                        "example": "106"
                                    },
                                    "ln_first_comment": {
                                        "type": "string",
                                        "description": "LinkedIn first comment; overrides `first_comment` on LinkedIn.",
                                        "example": "#linkedin #summersale"
                                    },
                                    "in_first_comment": {
                                        "type": "string",
                                        "description": "Instagram first comment (feed posts only); overrides `first_comment` on Instagram.",
                                        "example": "#instagram #summersale"
                                    },
                                    "fb_post_type": {
                                        "type": "string",
                                        "description": "Facebook post type. Case-insensitive; an unknown value keeps `feed`.",
                                        "enum": [
                                            "feed",
                                            "reel",
                                            "story"
                                        ],
                                        "default": "feed",
                                        "example": "feed"
                                    },
                                    "fb_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Custom cover image URL for the video on Facebook. Public image URL; copied to RecurPost storage unless `host_images_on_recurpost` is off. Ignored when the post has no `video_url`.",
                                        "example": "https://example.com/fb-cover.jpg"
                                    },
                                    "ln_document": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public URL of a document to post as a LinkedIn document (carousel) post: PDF, PPT, PPTX, DOC or DOCX, detected from the file bytes, not the file name. The file is downloaded and stored on RecurPost storage and the LinkedIn tab becomes a document post. A file of another type is left as given and ignored by the publisher. Google Drive share links are resolved.",
                                        "example": "https://example.com/catalog.pdf"
                                    },
                                    "ln_document_title": {
                                        "type": "string",
                                        "description": "Title shown on the LinkedIn document. Defaults to the file name without its extension.",
                                        "example": "Summer Catalog 2026"
                                    },
                                    "ln_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Custom cover image URL for the video on LinkedIn. Ignored when the post has no `video_url`.",
                                        "example": "https://example.com/ln-cover.jpg"
                                    },
                                    "in_post_type": {
                                        "type": "string",
                                        "description": "Instagram post type. Case-insensitive; an unknown value keeps `feed`. A reel needs a `video_url`.",
                                        "enum": [
                                            "feed",
                                            "story",
                                            "reel"
                                        ],
                                        "default": "feed",
                                        "example": "feed"
                                    },
                                    "in_reel_share_in_feed": {
                                        "type": "string",
                                        "description": "Whether a reel also appears in the profile feed. Only read when `in_post_type` is `reel`.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "in_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Custom cover image URL for an Instagram reel. Only applied when `in_post_type` is `reel` and the post has a `video_url`; copied to RecurPost storage because Meta fetches it at publish time.",
                                        "example": "https://example.com/in-cover.jpg"
                                    },
                                    "in_location_id": {
                                        "type": "string",
                                        "description": "Instagram place id to tag the post with. Take `id` and `name` from `/api/instagram_locations`.",
                                        "example": "212988663"
                                    },
                                    "in_location_name": {
                                        "type": "string",
                                        "description": "Name of the place in `in_location_id`.",
                                        "example": "Pune, Maharashtra"
                                    },
                                    "in_location_city": {
                                        "type": "string",
                                        "description": "City of the tagged place, as returned by `/api/instagram_locations`.",
                                        "example": "Pune"
                                    },
                                    "in_location_country": {
                                        "type": "string",
                                        "description": "Country of the tagged place, as returned by `/api/instagram_locations`.",
                                        "example": "India"
                                    },
                                    "in_image_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "People to tag on feed images. A JSON array of objects with `username`, `x` and `y` (fractions of the image width and height between 0 and 1) and `image` (1-based position in `image_url`, default 1). The leading `@` is optional.",
                                        "example": [
                                            {
                                                "image": 1,
                                                "username": "recurpost",
                                                "x": 0.5,
                                                "y": 0.4
                                            }
                                        ]
                                    },
                                    "in_reel_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Usernames to tag on a reel, as a JSON array or a comma-separated string. Only saved when the post has a `video_url`.",
                                        "example": [
                                            "recurpost",
                                            "jane_doe"
                                        ]
                                    },
                                    "in_collaborators": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Instagram usernames invited as collaborators, as a JSON array or a comma-separated string. At most 3.",
                                        "example": [
                                            "jane_doe"
                                        ]
                                    },
                                    "in_audio_id": {
                                        "type": "string",
                                        "description": "Instagram audio to lay under a reel, from `/api/instagram_audio_search`. Needs `in_post_type` reel, a `video_url` and `in_audio_account_id`.",
                                        "example": "1234567890123456"
                                    },
                                    "in_audio_account_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the Instagram account `/api/instagram_audio_search` ran for. Required with `in_audio_id`.",
                                        "example": "aK3mZ8vQr1=="
                                    },
                                    "in_audio_type": {
                                        "type": "string",
                                        "description": "Kind of audio behind `in_audio_id`.",
                                        "enum": [
                                            "music",
                                            "original_sound"
                                        ],
                                        "default": "music",
                                        "example": "music"
                                    },
                                    "in_audio_title": {
                                        "type": "string",
                                        "description": "Title of the audio, as the search returned it; stored with the reel.",
                                        "example": "Summer Nights"
                                    },
                                    "in_audio_artist": {
                                        "type": "string",
                                        "description": "Artist of the audio, as the search returned it.",
                                        "example": "The Examples"
                                    },
                                    "in_audio_duration_ms": {
                                        "type": "integer",
                                        "description": "Length of the audio in milliseconds, as the search returned it.",
                                        "example": 30000
                                    },
                                    "in_audio_volume": {
                                        "type": "integer",
                                        "description": "Volume of the added audio, 0 to 100.",
                                        "default": "100",
                                        "example": 100
                                    },
                                    "in_video_volume": {
                                        "type": "integer",
                                        "description": "Volume of the reel's own sound, 0 to 100.",
                                        "default": "100",
                                        "example": 100
                                    },
                                    "in_trial_reel": {
                                        "type": "string",
                                        "description": "Publish the reel as a trial reel, shown to non-followers first. `manual`: you decide in Instagram when to share it with followers; `performance`: Instagram shares it when it does well. Reels only.",
                                        "enum": [
                                            "manual",
                                            "performance"
                                        ],
                                        "example": "manual"
                                    },
                                    "in_product_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Instagram product tags on images: objects with `account_id` (encrypted, the account whose catalog holds the product), `product_id` (from `/api/instagram_products`), `image` (1-based position in `image_url`), `x` and `y` (0 to 1, default 0.5), and optionally `product_name` and `product_image`.",
                                        "example": [
                                            {
                                                "image": 1,
                                                "account_id": "aK3mZ8vQr1==",
                                                "product_id": "901000111222333",
                                                "x": 0.5,
                                                "y": 0.6
                                            }
                                        ]
                                    },
                                    "in_reel_product_tags": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Products tagged on a reel: objects with `account_id` (encrypted) and `product_id` (from `/api/instagram_products`), optionally `product_name` and `image_url`. Reels only.",
                                        "example": [
                                            {
                                                "account_id": "aK3mZ8vQr1==",
                                                "product_id": "901000111222333"
                                            }
                                        ]
                                    },
                                    "pi_title": {
                                        "type": "string",
                                        "description": "Pin title. The destination link of the pin is `url` or the first link in the text.",
                                        "example": "Summer Sale - Best Deals of the Season"
                                    },
                                    "gbp_cta": {
                                        "type": "string",
                                        "description": "Call-to-action button on the Google Business post. Case-insensitive. An unknown value or `None` saves no button. On a link post with no CTA given, `Learn more` pointing at the link is set automatically.",
                                        "enum": [
                                            "Learn more",
                                            "Sign up",
                                            "Buy",
                                            "Order online",
                                            "Book",
                                            "Call now",
                                            "Offer",
                                            "None"
                                        ],
                                        "default": "None",
                                        "example": "Learn more"
                                    },
                                    "gbp_cta_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link the button opens. Not used for `Call now`. With `gbp_cta=Offer` and no `gbp_redeem_offer_link`, this value doubles as the redeem link.",
                                        "example": "https://example.com/summer-sale"
                                    },
                                    "gbp_offer_title": {
                                        "type": "string",
                                        "description": "Offer title; offer fields are used when `gbp_cta` is `Offer`.",
                                        "example": "Summer Sale - 50% Off"
                                    },
                                    "gbp_offer_start_date": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Offer start, `YYYY-MM-DD HH:MM:SS`.",
                                        "example": "2026-06-01 00:00:00"
                                    },
                                    "gbp_offer_end_date": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Offer end, `YYYY-MM-DD HH:MM:SS`.",
                                        "example": "2026-06-30 23:59:59"
                                    },
                                    "gbp_offer_coupon_code": {
                                        "type": "string",
                                        "description": "Coupon code shown on the offer.",
                                        "example": "SUMMER50"
                                    },
                                    "gbp_offer_terms": {
                                        "type": "string",
                                        "description": "Terms and conditions of the offer.",
                                        "example": "Valid on selected items only"
                                    },
                                    "gbp_redeem_offer_link": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link to redeem the offer.",
                                        "example": "https://example.com/redeem"
                                    },
                                    "yt_title": {
                                        "type": "string",
                                        "description": "Video title. YouTube needs a `video_url`; `message` or `yt_message` is the description.",
                                        "example": "Summer Sale Announcement 2026"
                                    },
                                    "yt_category": {
                                        "type": "string",
                                        "description": "Category name, matched exactly against the list. An unknown or missing name falls back to the default category of the workspace owner's YouTube settings (Entertainment when none is set).",
                                        "enum": [
                                            "Film & Animation",
                                            "Autos & Vehicles",
                                            "Music",
                                            "Pets & Animals",
                                            "Sports",
                                            "Travel & Events",
                                            "Gaming",
                                            "People & Blogs",
                                            "Comedy",
                                            "Entertainment",
                                            "News & Politics",
                                            "Howto & Style",
                                            "Education",
                                            "Science & Technology",
                                            "Nonprofits & Activism"
                                        ],
                                        "example": "Howto & Style"
                                    },
                                    "yt_privacy_status": {
                                        "type": "string",
                                        "description": "Video privacy. Lower-cased and stored as given; use one of the listed values.",
                                        "enum": [
                                            "public",
                                            "private",
                                            "unlisted"
                                        ],
                                        "default": "public",
                                        "example": "public"
                                    },
                                    "yt_user_tags": {
                                        "type": "string",
                                        "description": "Video tags, comma-separated.",
                                        "example": "summer, sale, deals"
                                    },
                                    "yt_thumb": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Custom thumbnail URL for the YouTube video. Public image URL; copied to RecurPost storage unless `host_images_on_recurpost` is off.",
                                        "example": "https://example.com/yt-thumb.jpg"
                                    },
                                    "yt_video_made_for_kids": {
                                        "type": "string",
                                        "description": "Whether the video is made for kids. Only `yes` switches it on.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "no",
                                        "example": "no"
                                    },
                                    "tk_privacy_status": {
                                        "type": "string",
                                        "description": "Who can watch the TikTok video. Case-insensitive, spaces or underscores. Any other value is saved as `Public to Everyone`; omitted leaves it unset. `/api/tiktok_options` lists what the account allows.",
                                        "enum": [
                                            "Public to Everyone",
                                            "Mutual Follow Friends",
                                            "Self Only"
                                        ],
                                        "example": "Public to Everyone"
                                    },
                                    "tk_allow_comments": {
                                        "type": "string",
                                        "description": "Allow comments on the TikTok video. Only `no` switches it off.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_allow_duet": {
                                        "type": "string",
                                        "description": "Allow duets. Only `no` switches it off.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_allow_stitches": {
                                        "type": "string",
                                        "description": "Allow stitches. Only `no` switches it off.",
                                        "enum": [
                                            "yes",
                                            "no"
                                        ],
                                        "default": "yes",
                                        "example": "yes"
                                    },
                                    "tk_promote_own_brand": {
                                        "type": "integer",
                                        "description": "Set to `1` to mark the video as promoting your own brand (TikTok's content disclosure).",
                                        "enum": [
                                            0,
                                            1
                                        ],
                                        "default": "0",
                                        "example": 0
                                    },
                                    "tk_promote_other_brand": {
                                        "type": "integer",
                                        "description": "Set to `1` to mark the video as branded content for a third party.",
                                        "enum": [
                                            0,
                                            1
                                        ],
                                        "default": "0",
                                        "example": 0
                                    },
                                    "approve": {
                                        "type": "boolean",
                                        "description": "Save and approve in one step. Reviewers only.",
                                        "default": "false",
                                        "example": false
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "content_id",
                                    "message"
                                ],
                                "example": {
                                    "content_id": "cT5uV7wX==",
                                    "message": "Updated: our latest product is now 20% off! https://example.com/product"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "The app's confirmation: `Post saved successfully.` or `Post saved and approved successfully.`"
                                        },
                                        "content_id": {
                                            "type": "string",
                                            "description": "The encrypted id sent."
                                        },
                                        "approved": {
                                            "type": "boolean",
                                            "description": "`true` when the post was approved in this call."
                                        },
                                        "counts": {
                                            "type": "object",
                                            "properties": {
                                                "to_review": {
                                                    "type": "integer",
                                                    "description": "Posts waiting for your decision, after this call."
                                                },
                                                "submitted": {
                                                    "type": "integer",
                                                    "description": "Your posts still waiting on others."
                                                },
                                                "rejected": {
                                                    "type": "integer",
                                                    "description": "Your posts that were rejected."
                                                },
                                                "rejected_by_you": {
                                                    "type": "integer",
                                                    "description": "Posts of others you rejected."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Post saved successfully.",
                                    "content_id": "cT5uV7wX==",
                                    "approved": false,
                                    "counts": {
                                        "to_review": 2,
                                        "submitted": 1,
                                        "rejected": 1,
                                        "rejected_by_you": 0
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (content_id or message is missing.)\n\nBad Request Please try again later (message blank, or library_id / id missing or not decryptable.)\n\n<message from the app> (The update failed for another reason (for example the content is not in that library); the app's text is relayed.)\n\nimage_url takes at most 20 images. (More than 20 image URLs.)\n\nalt_text entries may have at most 1000 characters. (An alt_text entry is longer than 1000 characters.)\n\nin_collaborators takes at most 3 usernames. (More than 3 collaborators.)\n\nin_reel_tags needs a video_url. (in_reel_tags sent on a post without a video.)\n\nin_image_tags entries need username, x and y between 0 and 1, and image as a position in image_url. (An in_image_tags entry is malformed or points past the last image.)\n\nmedia_order may only hold the URLs given in image_url and video_url. (media_order names a URL that is not in the post.)\n\ntwitter_thread takes at most 25 further tweets. (More than 25 thread items.)\n\nin_audio_id needs in_post_type reel with a video_url, in_audio_account_id (the account instagram_audio_search ran for), in_audio_type music or original_sound, and volumes from 0 to 100. (in_audio_id is sent without those conditions.)\n\nin_trial_reel is manual or performance, on in_post_type reel only. (in_trial_reel has another value or the post is not a reel.)\n\nin_product_tags entries need account_id, product_id (from instagram_products), image as a position in image_url, and x and y between 0 and 1. (An in_product_tags entry is malformed or points past the last image.)\n\nin_reel_product_tags entries need account_id and product_id, on in_post_type reel only. (An in_reel_product_tags entry is malformed or the post is not a reel.)\n\nfb_mentions holds page ids from mention_search, as a list or as {page_id, name} items. (An fb_mentions entry is not a numeric page id.)\n\nfb_mentions takes at most 10 pages. (More than 10 pages in fb_mentions.)\n\nfb_background_id takes a background id from facebook_backgrounds, on a post without image_url or video_url. (fb_background_id is sent with media, or is not a plain id.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)\n\n<prefix>_image_url / <prefix>_video_url must leave <network> at least one image or a video. (A per-network media field is sent empty.)\n\nyt_image_url is not accepted; YouTube takes yt_video_url only. (Images sent for YouTube.)\n\n<prefix>_image_url and <prefix>_video_url cannot be combined; only Instagram and Threads take images and a video together. (Images and a video for one network other than Instagram or Threads.)\n\n<prefix>_image_url takes at most <n> images for <network>. (More images than that network allows. Instagram and Threads count images and video together and answer \"_image_url and _video_url take at most  media items together for .\")\n\n<prefix>_media_order may only hold the URLs given in <prefix>_image_url and <prefix>_video_url. (A per-network order names a URL outside that network's own media.)\n\n<prefix>_alt_text entries may have at most 1000 characters. (A per-network alt text entry is longer than 1000 characters.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The post is not the workspace owner's.)\n\nYou are neither the author nor a reviewer of this post. (The caller did not write the post and is not one of its reviewers.)\n\nOnly a reviewer of this post can approve it. (approve=true from the author, who is no reviewer.)\n\nYou have maximum allowed number of posts in your library. Please <upgrade wording> or delete few posts to add new ones. (approve=true would pass the owner's library post limit.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nThis post is not in the approval flow. (The post was never sent for approval or was approved already.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Content validation failed! (The per-network validator refused the content; error_details lists the reasons.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/approval_resend": {
            "post": {
                "tags": [
                    "Approvals"
                ],
                "summary": "Send a rejected post back to its reviewers.",
                "description": "Puts a rejected post back in front of its reviewers: it returns to waiting, the reviewers get the approval request mail again, and a fresh decision is recorded with `/api/approval_decide`. Only the post's author may do this, and only for a rejected post. Edit the post first from RecurPost; this call sends the content as it stands.\n\nSends mail to every reviewer: Each successful call mails the reviewers again. The post goes back to `submitted` in `/api/approval_list` and the reviewers see it under `to_review`.",
                "operationId": "approval_resend",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "content_id": {
                                        "type": "string",
                                        "description": "Encrypted library post id from `items[].id` of `/api/approval_list` (scope `rejected`).",
                                        "example": "sP9cM3xY1z=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "content_id"
                                ],
                                "example": {
                                    "content_id": "sP9cM3xY1z=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Post sent back to its reviewers.`"
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Post sent back to its reviewers."
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\ncontent_id is required. (content_id is missing or does not decrypt to one post id.)\n\nSomething went wrong (The app refused; its own text is relayed when it sent one, for example `This post is not rejected.`)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The post does not belong to the workspace owner.)\n\nYou are neither the author nor a reviewer of this post. (The post is someone else's and you were not asked to review it.)\n\nOnly the post's author can send it back for approval. (You are a reviewer of the post, not its author.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nThis post is not in the approval flow. (The post was never sent for approval.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Only a rejected post can be sent back; this one is approved. (The post is not rejected. The last words are `approved` or `still waiting` accordingly.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/approval_delete": {
            "post": {
                "tags": [
                    "Approvals"
                ],
                "summary": "Remove a post from the approval flow for good.",
                "description": "Deletes a post that is in the approval flow, whether waiting, approved or rejected, together with its comments. The author and the reviewers of the post may delete it. The post never reaches the library; an approved post that already joined the library is the library's and is not touched here.\n`confirm=true` is required.\n\nNot reversible: The post, its media links and its comment thread are gone; the author has to compose it again. Reviewers who want the post changed should reject it with `/api/approval_decide` instead.",
                "operationId": "approval_delete",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "content_id": {
                                        "type": "string",
                                        "description": "Encrypted library post id from `items[].id` of `/api/approval_list`.",
                                        "example": "sP9cM3xY1z=="
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Must be `true`; the call is refused without it.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "content_id",
                                    "confirm"
                                ],
                                "example": {
                                    "content_id": "sP9cM3xY1z==",
                                    "confirm": true
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Post deleted.`"
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Post deleted."
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\ncontent_id is required. (content_id is missing or does not decrypt to one post id.)\n\nSend confirm=true to delete the post from the approval flow; it is removed for good. (confirm is missing or not true.)\n\nSomething went wrong (The app refused; its own text is relayed when it sent one, for example `This post is no longer in the approval queue.`)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The post does not belong to the workspace owner.)\n\nYou are neither the author nor a reviewer of this post. (The post is someone else's and you were not asked to review it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nThis post is not in the approval flow. (The post was never sent for approval, or was deleted already.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workflow_board": {
            "post": {
                "tags": [
                    "Workflow Board"
                ],
                "summary": "Columns and cards of the board, for one workspace or for every workspace of the owner you belong to.",
                "description": "Returns the board of the workspace owner: its columns (Ideas, the owner's stages, Scheduled) with the cards in each, the team members who can be assigned, and the workflow settings.\nScoping. The board is the owner's, not yours. `workspace_id` (or your default workspace when omitted) picks the owner; the board then spans every workspace of that owner you are an active member of. The owner's signup default workspace is kept off the board while other workspaces exist, as on the dashboard; passing its id is the same as passing none. When you pass any other `workspace_id` only that workspace's cards are returned; otherwise all board workspaces are, unless `workspace_ids` narrows them. Every card carries its own `workspace_id`.\nCard shape. This is the full card object; `/api/workflow_card`, `/api/workflow_card_save` and `/api/workflow_card_move` return the same fields.\n\nWhose board: Team members see the board of the owner whose workspace they pass. Your own signup workspace is the default when you omit `workspace_id`, so as a team member pass the agency's `workspace_id` to reach their board.\n\nTimezones: `target_date` is the owner's wall clock as typed. `schedule.first_at` and the schedule times of `/api/workflow_card` are converted to the owner's timezone. `created_at` and `updated_at` are the app's stored UTC values.",
                "operationId": "workflow_board",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. When given, the board shows this workspace only; the owner's signup default workspace (`is_default` in the list) gives the whole board instead, the same as leaving it out.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "workspace_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted workspace ids (array or comma-separated) to show instead of the whole board. Every id must be a board workspace you belong to. Ignored in favour of `workspace_id` when both are sent and `workspace_ids` is blank.",
                                        "example": [
                                            "nX2k9Qp7Lw==",
                                            "qR5sT6uV7w=="
                                        ]
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "has_workflow": {
                                            "type": "boolean",
                                            "description": "false when the owner has not set up a workflow yet; `columns` is then empty and the fields after `workspaces` are omitted."
                                        },
                                        "workspaces": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Board workspaces you belong to, by name.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted workspace id."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Workspace name."
                                                    },
                                                    "selected": {
                                                        "type": "boolean",
                                                        "description": "true when this workspace's cards are in the response."
                                                    }
                                                }
                                            }
                                        },
                                        "columns": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Board columns in order: Ideas (when enabled), each stage, Scheduled.",
                                                "properties": {
                                                    "key": {
                                                        "type": "string",
                                                        "description": "Column key: `ideas`, `stage-<stage_id>` or `scheduled`."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Column name as the owner named the stage."
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "description": "`ideas`, `work`, `review`, `client` (client approval stage) or `scheduled`."
                                                    },
                                                    "stage_id": {
                                                        "type": "integer",
                                                        "description": "Stage id to use in `stage_id`, `to` and `return_stage_id`; 0 for Ideas and Scheduled."
                                                    },
                                                    "color": {
                                                        "type": "string",
                                                        "description": "Stage colour name; blank for Ideas and Scheduled."
                                                    },
                                                    "cards": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "array",
                                                            "items": [],
                                                            "description": "Cards in the column, in board order. Each is a card object as described below.",
                                                            "properties": {
                                                                "id": {
                                                                    "type": "integer",
                                                                    "description": "Plain numeric card id."
                                                                },
                                                                "kind": {
                                                                    "type": "string",
                                                                    "description": "`idea` or `post`."
                                                                },
                                                                "workspace_id": {
                                                                    "type": "string",
                                                                    "description": "Encrypted id of the workspace the card belongs to."
                                                                },
                                                                "column": {
                                                                    "type": "string",
                                                                    "description": "`ideas`, `stage` or `scheduled`."
                                                                },
                                                                "stage_id": {
                                                                    "type": "integer",
                                                                    "description": "Stage the card is in; 0 in Ideas and Scheduled."
                                                                },
                                                                "title": {
                                                                    "type": "string",
                                                                    "description": "Card title."
                                                                },
                                                                "description": {
                                                                    "type": "string",
                                                                    "description": "Card description or caption draft."
                                                                },
                                                                "platforms": {
                                                                    "type": "array",
                                                                    "items": {
                                                                        "type": "array",
                                                                        "items": [],
                                                                        "description": "Platform keys the card targets: `instagram`, `facebook`, `linkedin`, `twitter`, `google`, `pinterest`, `youtube`, `tiktok`, `threads`, `bluesky`."
                                                                    }
                                                                },
                                                                "account_ids": {
                                                                    "type": "array",
                                                                    "items": {
                                                                        "type": "array",
                                                                        "items": [],
                                                                        "description": "Encrypted ids of the social accounts the card will publish to."
                                                                    }
                                                                },
                                                                "target_date": {
                                                                    "type": "string",
                                                                    "format": "date-time",
                                                                    "description": "Target date in the owner's wall clock, `YYYY-MM-DD HH:MM:SS`; blank when none."
                                                                },
                                                                "assignee": {
                                                                    "type": "object",
                                                                    "description": "`{id, name}` of the member assigned, or null."
                                                                },
                                                                "labels": {
                                                                    "type": "array",
                                                                    "items": {
                                                                        "type": "array",
                                                                        "items": [],
                                                                        "description": "Labels on the card: `{id, name, color}`."
                                                                    }
                                                                },
                                                                "media": {
                                                                    "type": "array",
                                                                    "items": {
                                                                        "type": "array",
                                                                        "items": [],
                                                                        "description": "Attached files: `{url, type}` with type `image` or `video`."
                                                                    }
                                                                },
                                                                "status": {
                                                                    "type": "string",
                                                                    "description": "Review state the app keeps on the card, for example `open`, `pending_review`, `awaiting_client`, `changes_requested`, `approved` or `scheduled`."
                                                                },
                                                                "client_approval": {
                                                                    "type": "boolean",
                                                                    "description": "true when the card is shared with the client for approval."
                                                                },
                                                                "urgent": {
                                                                    "type": "boolean",
                                                                    "description": "true when an urgent client approval was requested."
                                                                },
                                                                "source": {
                                                                    "type": "string",
                                                                    "description": "`team`, or `client` for ideas the client suggested."
                                                                },
                                                                "schedule": {
                                                                    "type": "object",
                                                                    "properties": {
                                                                        "count": {
                                                                            "type": "integer",
                                                                            "description": "Number of schedule slots on the card."
                                                                        },
                                                                        "first_at": {
                                                                            "type": "string",
                                                                            "format": "date-time",
                                                                            "description": "Earliest slot in the owner's timezone, or null."
                                                                        }
                                                                    }
                                                                },
                                                                "post_id": {
                                                                    "type": "integer",
                                                                    "description": "Plain id of the queue post once the card is scheduled; 0 before."
                                                                },
                                                                "created_by": {
                                                                    "type": "object",
                                                                    "description": "`{id, name}` of the creator, or null for client-created cards."
                                                                },
                                                                "created_at": {
                                                                    "type": "string",
                                                                    "format": "date-time",
                                                                    "description": "Creation time as stored by the app (UTC)."
                                                                },
                                                                "updated_at": {
                                                                    "type": "string",
                                                                    "format": "date-time",
                                                                    "description": "Last change as stored by the app (UTC)."
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        },
                                        "total_cards": {
                                            "type": "integer",
                                            "description": "Cards across all returned columns."
                                        },
                                        "members": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Team members on the board: `{id, name, role}`. `id` is the encrypted user id to use in `assignee_user_id` and `user_id`."
                                            }
                                        },
                                        "settings": {
                                            "type": "object",
                                            "properties": {
                                                "ideas_enabled": {
                                                    "type": "boolean",
                                                    "description": "Whether the Ideas column is on."
                                                },
                                                "client_approval_default": {
                                                    "type": "boolean",
                                                    "description": "Whether new posts are shared with the client by default."
                                                },
                                                "share_ideas_default": {
                                                    "type": "boolean",
                                                    "description": "Whether new ideas are shared with the client by default."
                                                },
                                                "has_client_stage": {
                                                    "type": "boolean",
                                                    "description": "Whether the workflow has a client approval stage."
                                                }
                                            }
                                        },
                                        "can_create": {
                                            "type": "boolean",
                                            "description": "Whether your role may create cards."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "has_workflow": true,
                                    "workspaces": [
                                        {
                                            "id": "nX2k9Qp7Lw==",
                                            "name": "Acme Agency",
                                            "selected": true
                                        }
                                    ],
                                    "columns": [
                                        {
                                            "key": "ideas",
                                            "name": "Ideas",
                                            "type": "ideas",
                                            "stage_id": 0,
                                            "color": "",
                                            "cards": []
                                        },
                                        {
                                            "key": "stage-7",
                                            "name": "Design",
                                            "type": "work",
                                            "stage_id": 7,
                                            "color": "blue",
                                            "cards": [
                                                {
                                                    "id": 512,
                                                    "kind": "post",
                                                    "workspace_id": "nX2k9Qp7Lw==",
                                                    "column": "stage",
                                                    "stage_id": 7,
                                                    "title": "Launch teaser",
                                                    "description": "Short teaser for the spring launch.",
                                                    "platforms": [
                                                        "facebook",
                                                        "instagram"
                                                    ],
                                                    "account_ids": [
                                                        "aB3cD4eF5g==",
                                                        "hJ6kL7mN8p=="
                                                    ],
                                                    "target_date": "2026-11-01 15:00:00",
                                                    "assignee": {
                                                        "id": "Sl7mN2vB4Q==",
                                                        "name": "Sam Lee"
                                                    },
                                                    "labels": [
                                                        {
                                                            "id": 3,
                                                            "name": "Promo",
                                                            "color": "rose"
                                                        }
                                                    ],
                                                    "media": [
                                                        {
                                                            "url": "https://cdn.recurpost.com/media/12/teaser.jpg",
                                                            "type": "image"
                                                        }
                                                    ],
                                                    "status": "open",
                                                    "client_approval": true,
                                                    "urgent": false,
                                                    "source": "team",
                                                    "schedule": {
                                                        "count": 2,
                                                        "first_at": "2026-11-01 10:00:00"
                                                    },
                                                    "post_id": 0,
                                                    "created_by": {
                                                        "id": "Jd3xP0wQ1A==",
                                                        "name": "Jane Doe"
                                                    },
                                                    "created_at": "2026-10-01 10:00:00",
                                                    "updated_at": "2026-10-02 10:00:00"
                                                }
                                            ]
                                        },
                                        {
                                            "key": "scheduled",
                                            "name": "Scheduled",
                                            "type": "scheduled",
                                            "stage_id": 0,
                                            "color": "",
                                            "cards": []
                                        }
                                    ],
                                    "total_cards": 1,
                                    "members": [
                                        {
                                            "id": "Jd3xP0wQ1A==",
                                            "name": "Jane Doe",
                                            "role": "Owner"
                                        },
                                        {
                                            "id": "Sl7mN2vB4Q==",
                                            "name": "Sam Lee",
                                            "role": "Designer"
                                        }
                                    ],
                                    "settings": {
                                        "ideas_enabled": true,
                                        "client_approval_default": false,
                                        "share_ideas_default": true,
                                        "has_client_stage": true
                                    },
                                    "can_create": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nThis workspace is not on the board. (workspace_id names a workspace of this owner that is not part of their board.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "You are not a member of any workspace on this board. (The owner has no workspace you are an active member of.)\n\nworkspace_ids must name workspaces of this board that you belong to. (workspace_ids holds an invalid id or a workspace outside the board.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of (a pending invite does not count).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The board read failed inside the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workflow_card": {
            "post": {
                "tags": [
                    "Workflow Board"
                ],
                "summary": "One card with its schedule, activity, the actions you may take and where it can go next.",
                "description": "Returns one card in the card shape of `/api/workflow_board`, extended with its stage, the next column, the stages it can be sent back to, the actions your role may take on it right now, every schedule slot, and the activity log (comments, moves, approvals). The card must sit on a workspace of the board.",
                "operationId": "workflow_card",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Plain numeric card id from `/api/workflow_board`.",
                                        "example": 512
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. Picks the board owner; the card may be on any workspace of that board.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 512
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "card": {
                                            "type": "object",
                                            "description": "The card object of `/api/workflow_board` plus the fields below.",
                                            "properties": {
                                                "stage_name": {
                                                    "type": "string",
                                                    "description": "Name of the column the card is in."
                                                },
                                                "column_type": {
                                                    "type": "string",
                                                    "description": "`ideas`, `work`, `review`, `client` or `scheduled`."
                                                },
                                                "next": {
                                                    "type": "object",
                                                    "description": "Next column as `{stage_id, name, type}`, or null at the end of the workflow."
                                                },
                                                "return_stages": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "array",
                                                        "items": [],
                                                        "description": "Stages the card may be sent back to with `request_changes`: `{id, name}`."
                                                    }
                                                },
                                                "return_default_stage_id": {
                                                    "type": "integer",
                                                    "description": "Stage used by `request_changes` when no `return_stage_id` is sent; 0 when none."
                                                },
                                                "actions": {
                                                    "type": "object",
                                                    "properties": {
                                                        "edit": {
                                                            "type": "boolean",
                                                            "description": "Whether you may edit the card."
                                                        },
                                                        "delete": {
                                                            "type": "boolean",
                                                            "description": "Whether you may delete it."
                                                        },
                                                        "reassign": {
                                                            "type": "boolean",
                                                            "description": "Whether you may change the assignee."
                                                        },
                                                        "advance": {
                                                            "type": "boolean",
                                                            "description": "Whether you may move it to the next column."
                                                        },
                                                        "request_changes": {
                                                            "type": "boolean",
                                                            "description": "Whether you may send it back."
                                                        },
                                                        "send_client": {
                                                            "type": "boolean",
                                                            "description": "Whether you may hand it to the client (dashboard only)."
                                                        },
                                                        "urgent": {
                                                            "type": "boolean",
                                                            "description": "Whether you may request an urgent client approval (dashboard only)."
                                                        },
                                                        "publish": {
                                                            "type": "boolean",
                                                            "description": "Whether you may schedule it directly."
                                                        },
                                                        "advance_blocked_by": {
                                                            "type": "string",
                                                            "description": "Why `advance` is false, blank when it is allowed."
                                                        },
                                                        "request_changes_blocked_by": {
                                                            "type": "string",
                                                            "description": "Why `request_changes` is false, blank when it is allowed."
                                                        }
                                                    }
                                                },
                                                "schedules": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "array",
                                                        "items": [],
                                                        "description": "Every schedule slot as `{at}` in the owner's timezone, earliest first."
                                                    }
                                                },
                                                "schedule": {
                                                    "type": "object",
                                                    "properties": {
                                                        "count": {
                                                            "type": "integer",
                                                            "description": "Number of slots."
                                                        },
                                                        "first_at": {
                                                            "type": "string",
                                                            "format": "date-time",
                                                            "description": "Earliest slot, or null."
                                                        }
                                                    }
                                                },
                                                "queued_caption": {
                                                    "type": "string",
                                                    "description": "Caption of the queue post once scheduled; blank before."
                                                },
                                                "activity": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "array",
                                                        "items": [],
                                                        "description": "Activity log, as the app orders it.",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "Activity id."
                                                            },
                                                            "type": {
                                                                "type": "string",
                                                                "description": "Event key such as `post_created`, `edited`, `moved`, `assigned`, `sent_back`, `sent_to_client`, `client_approved`, `client_comment`, `approved_scheduled`, `published`, `publish_failed`."
                                                            },
                                                            "by": {
                                                                "type": "object",
                                                                "description": "`{id, name}` of the member; `{id: 0, name: \"Client\"}` for client actions."
                                                            },
                                                            "text": {
                                                                "type": "string",
                                                                "description": "Comment text, blank for system events."
                                                            },
                                                            "internal": {
                                                                "type": "boolean",
                                                                "description": "true for internal notes hidden from the client."
                                                            },
                                                            "details": {
                                                                "type": "object",
                                                                "description": "Event details the app recorded, or null."
                                                            },
                                                            "at": {
                                                                "type": "string",
                                                                "format": "date-time",
                                                                "description": "When it happened, in the owner's timezone."
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        },
                                        "members": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "The members this card can be handed to where it sits: `{id, name, role}`. In a stage these are the owner, the Account Manager and the members whose role is attached to the stage (plus the current assignee); an idea lists every member of the workspace; a card with the client or in the queue lists nobody. Use `id` in `user_id` when reassigning."
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "card": {
                                        "id": 512,
                                        "kind": "post",
                                        "workspace_id": "nX2k9Qp7Lw==",
                                        "column": "stage",
                                        "stage_id": 7,
                                        "title": "Launch teaser",
                                        "description": "Short teaser for the spring launch.",
                                        "platforms": [
                                            "facebook",
                                            "instagram"
                                        ],
                                        "account_ids": [
                                            "aB3cD4eF5g==",
                                            "hJ6kL7mN8p=="
                                        ],
                                        "target_date": "",
                                        "assignee": {
                                            "id": "Sl7mN2vB4Q==",
                                            "name": "Sam Lee"
                                        },
                                        "labels": [],
                                        "media": [
                                            {
                                                "url": "https://cdn.recurpost.com/media/12/teaser.jpg",
                                                "type": "image"
                                            }
                                        ],
                                        "status": "open",
                                        "client_approval": true,
                                        "urgent": false,
                                        "source": "team",
                                        "schedule": {
                                            "count": 1,
                                            "first_at": "2026-11-01 10:00:00"
                                        },
                                        "post_id": 0,
                                        "created_by": {
                                            "id": "Jd3xP0wQ1A==",
                                            "name": "Jane Doe"
                                        },
                                        "created_at": "2026-10-01 10:00:00",
                                        "updated_at": "2026-10-02 10:00:00",
                                        "stage_name": "Design",
                                        "column_type": "work",
                                        "next": {
                                            "stage_id": 8,
                                            "name": "Review",
                                            "type": "review"
                                        },
                                        "return_stages": [],
                                        "return_default_stage_id": 0,
                                        "actions": {
                                            "edit": true,
                                            "delete": true,
                                            "reassign": true,
                                            "advance": false,
                                            "request_changes": false,
                                            "send_client": false,
                                            "urgent": false,
                                            "publish": false,
                                            "advance_blocked_by": "Select at least one social account for this post.",
                                            "request_changes_blocked_by": ""
                                        },
                                        "schedules": [
                                            {
                                                "at": "2026-11-01 10:00:00"
                                            }
                                        ],
                                        "queued_caption": "",
                                        "activity": [
                                            {
                                                "id": 1,
                                                "type": "client_comment",
                                                "by": {
                                                    "id": 0,
                                                    "name": "Client"
                                                },
                                                "text": "Looks good",
                                                "internal": false,
                                                "details": null,
                                                "at": "2026-10-02 10:00:00"
                                            }
                                        ]
                                    },
                                    "members": [
                                        {
                                            "id": "Jd3xP0wQ1A==",
                                            "name": "Jane Doe",
                                            "role": "Owner"
                                        },
                                        {
                                            "id": "Sl7mN2vB4Q==",
                                            "name": "Sam Lee",
                                            "role": "Designer"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or not a positive integer.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nThis workspace is not on the board. (workspace_id names a workspace of this owner that is not part of their board.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "You are not a member of any workspace on this board. (The owner has no workspace you are an active member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nCard not found. (No card with this id sits on a workspace of the board.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The card read failed inside the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workflow_card_save": {
            "post": {
                "tags": [
                    "Workflow Board"
                ],
                "summary": "Create an idea or a post card, or update an existing card.",
                "description": "Without `id` creates a card: `kind` `idea` goes to the Ideas column, `kind` `post` starts in the stage you name with `stage_id`. With `id` updates that card; fields left out keep their value, and only the fields you send are written.\nEach field is checked against the owner before the app is called: platforms against the known keys, accounts and labels against the owner's, media URLs must be public, schedule slots well formed. The app then applies the dashboard rules (your role's create and edit permissions, the Ideas column being enabled, accounts belonging to the card's workspace, no schedule slot in the past).\n\nUpdates are partial: Only fields present in the request are written. Clearing a field means sending it empty (`description`, `target_date`, `account_ids`, `label_ids`, `media`, `schedule` as `\"\"` or `[]`). On update `kind` and `stage_id` are ignored.\n\nSchedule slots are drafts: The slots you send stay on the card until it reaches the Scheduled column (`/api/workflow_card_move` with `advance` and `to_scheduled`, or client approval); only then do they become queue posts. The `at` time is read in the account's timezone, and the card reads it back in the owner's.\n\nMedia is re-hosted on save: RecurPost downloads each media URL when the card is saved and stores its own copy; the card then reads back RecurPost URLs, not the ones you sent.",
                "operationId": "workflow_card_save",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "title": {
                                        "type": "string",
                                        "description": "Card title. Required on create; on update a blank or missing title keeps the stored one.",
                                        "example": "Launch teaser"
                                    },
                                    "id": {
                                        "type": "integer",
                                        "description": "Plain numeric card id to update. Omit to create.",
                                        "example": 512
                                    },
                                    "kind": {
                                        "type": "string",
                                        "description": "On create only: `idea` or `post`.",
                                        "enum": [
                                            "idea",
                                            "post"
                                        ],
                                        "default": "idea",
                                        "example": "post"
                                    },
                                    "stage_id": {
                                        "type": "integer",
                                        "description": "Required when creating a `post`: the stage it starts in, from `columns[].stage_id` of `/api/workflow_board`. Ignored on update; move cards with `/api/workflow_card_move`.",
                                        "example": 7
                                    },
                                    "description": {
                                        "type": "string",
                                        "description": "Description or caption draft. Send an empty string to clear it.",
                                        "example": "Short teaser for the spring launch."
                                    },
                                    "platforms": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Platform keys (array, JSON-encoded array string or comma-separated): `instagram`, `facebook`, `linkedin`, `twitter`, `google`, `pinterest`, `youtube`, `tiktok`, `threads`, `bluesky`.",
                                        "example": [
                                            "facebook",
                                            "instagram"
                                        ]
                                    },
                                    "account_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted social account ids (array or comma-separated) the card will publish to. They must belong to the workspace owner, and the app requires them to be connected to the card's workspace. Send an empty string or empty array to clear.",
                                        "example": [
                                            "aB3cD4eF5g=="
                                        ]
                                    },
                                    "target_date": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Target date in the owner's wall clock, `YYYY-MM-DD` or `YYYY-MM-DD HH:MM`. Send an empty string to clear.",
                                        "example": "2026-11-01 15:00"
                                    },
                                    "assignee_user_id": {
                                        "type": "string",
                                        "description": "Encrypted user id from `members[]` to assign the card to; 0 clears the assignee. The app checks the member may work the stage.",
                                        "example": "Sl7mN2vB4Q=="
                                    },
                                    "share_with_client": {
                                        "type": "boolean",
                                        "description": "Whether the card is shared with the client for approval. Defaults to the workflow setting on create.",
                                        "example": true
                                    },
                                    "label_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Plain numeric label ids (array or comma-separated) of the owner's labels. Replaces the current labels; an empty value clears them.",
                                        "example": [
                                            3
                                        ]
                                    },
                                    "media": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Up to 10 attachments as publicly reachable http or https URLs. Each entry is a URL string or `{url, type}` with type `image` or `video`; without a type, `.mp4`, `.mov`, `.m4v` and `.webm` count as video. Replaces the current media.",
                                        "example": [
                                            "https://example.com/teaser.jpg",
                                            {
                                                "url": "https://example.com/clip",
                                                "type": "video"
                                            }
                                        ]
                                    },
                                    "schedule": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Draft schedule slots, one object per slot: `{account_id, at}` with `at` as `YYYY-MM-DD HH:MM` (wall clock of that account's timezone), or `{account_id, date, best_time: true}` with `date` as `YYYY-MM-DD` to let RecurPost pick the best time that day. `account_id` is an encrypted account id. Replaces the current slots; an empty list clears them.",
                                        "example": [
                                            {
                                                "account_id": "aB3cD4eF5g==",
                                                "at": "2026-11-01 15:30"
                                            },
                                            {
                                                "account_id": "aB3cD4eF5g==",
                                                "date": "2026-11-02",
                                                "best_time": true
                                            }
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. On create the card is placed in this workspace; without it, or with the owner's signup default workspace, in the first board workspace by name.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "title"
                                ],
                                "example": {
                                    "title": "Launch teaser"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "The app's confirmation, normally `Saved`."
                                        },
                                        "card": {
                                            "type": "object",
                                            "description": "The saved card in the card shape of `/api/workflow_board`; null when the app returned no card."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Saved",
                                    "card": {
                                        "id": 512,
                                        "kind": "post",
                                        "workspace_id": "nX2k9Qp7Lw==",
                                        "column": "stage",
                                        "stage_id": 7,
                                        "title": "Launch teaser",
                                        "description": "Short teaser for the spring launch.",
                                        "platforms": [
                                            "facebook",
                                            "instagram"
                                        ],
                                        "account_ids": [
                                            "aB3cD4eF5g=="
                                        ],
                                        "target_date": "2026-11-01 15:00:00",
                                        "assignee": {
                                            "id": "Sl7mN2vB4Q==",
                                            "name": "Sam Lee"
                                        },
                                        "labels": [
                                            {
                                                "id": 3,
                                                "name": "Promo",
                                                "color": "rose"
                                            }
                                        ],
                                        "media": [
                                            {
                                                "url": "https://cdn.recurpost.com/media/12/teaser.jpg",
                                                "type": "image"
                                            },
                                            {
                                                "url": "https://cdn.recurpost.com/media/12/clip.mp4",
                                                "type": "video"
                                            }
                                        ],
                                        "status": "open",
                                        "client_approval": true,
                                        "urgent": false,
                                        "source": "team",
                                        "schedule": {
                                            "count": 2,
                                            "first_at": "2026-11-01 15:30:00"
                                        },
                                        "post_id": 0,
                                        "created_by": {
                                            "id": "Jd3xP0wQ1A==",
                                            "name": "Jane Doe"
                                        },
                                        "created_at": "2026-10-22 09:12:00",
                                        "updated_at": "2026-10-22 09:12:00"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (Creating without a title.)\n\nkind must be idea or post. (Creating with another kind.)\n\nA post needs the stage_id it starts in; see workflow_board for the stages. (Creating a post without a positive stage_id.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nThis workspace is not on the board. (workspace_id names a workspace of this owner that is not part of their board.)\n\nplatforms must be among instagram, facebook, linkedin, twitter, google, pinterest, youtube, tiktok, threads, bluesky. (platforms holds an unknown key.)\n\naccount_ids must be social accounts of this workspace's owner. (An id does not decrypt or is not one of the owner's accounts.)\n\ntarget_date must be a date like 2026-10-20 or 2026-10-20 15:00. (target_date does not parse.)\n\nlabel_ids 999 are not labels of this account. (A label id is not one of the owner's; the message lists the offending ids.)\n\nmedia must be publicly reachable http or https URLs. (A media URL has another scheme, no host, or resolves to a private or reserved address.)\n\nmedia takes at most 10 files. (More than 10 media entries.)\n\nschedule must be a list of {account_id, at} or {account_id, date, best_time} objects. (A slot is not an object.)\n\nEach schedule slot needs a valid account_id. (A slot's account_id does not decrypt to one account id.)\n\nA best_time slot needs date as Y-m-d. (best_time is true and date is not YYYY-MM-DD.)\n\nA schedule slot needs at as Y-m-d H:i, or date with best_time true. (A slot has neither a valid at nor a best_time date.)\n\nThe Ideas stage is disabled in this workflow. (Creating an idea while the workflow has Ideas switched off.)\n\nPlease choose a stage. (The app did not accept the stage.)\n\nSomething went wrong (Other app-side refusals are relayed with their own text, for example an account not connected to the card's workspace or a schedule slot in the past.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "You are not a member of any workspace on this board. (The owner has no workspace you are an active member of.)\n\nTo create posts, please ask your workspace owner to give you the \"...\" permission. (Your role may not create cards or edit this card; the text names the missing permission.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nCard not found. (id names no card on a workspace of the board.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workflow_card_move": {
            "post": {
                "tags": [
                    "Workflow Board"
                ],
                "summary": "Move, advance, convert, reassign a card or send it back for changes.",
                "description": "One endpoint for every board action, selected with `action`:\n- `move`: put the card in the stage named by `to`, or back in Ideas with `to` `ideas`.\n- `advance`: move the card to the next column; with `to_scheduled` true it jumps straight to Scheduled and its draft slots become queue posts.\n- `convert`: turn an idea into a post in the workflow's first work stage (the first stage of any type when there is no work stage); `share_with_client` sets whether the client sees it.\n- `reassign`: set the assignee to `user_id`, 0 to clear.\n- `request_changes`: send the card back with a `comment` for the author, to `return_stage_id` or the workflow's default return stage.\n\nWith every action except `reassign`, `assignee_user_id` names who picks the card up where it lands. The app enforces the dashboard rules: your role's permissions, stage gates (accounts and caption present, client approval before scheduling, no slot in the past) and the card still being where you think it is.\n\nScheduling is a side effect: `advance` with `to_scheduled` true (or an advance whose next column is Scheduled) turns the card's draft slots into real queue posts and sets `post_id`. The app refuses when a slot is already in the past.\n\nNotifications: Moves, reassignments and change requests trigger the same emails and push notifications the dashboard sends to the people involved, according to the owner's notification settings.\n\nClient hand-over: Sending a card to the client and requesting an urgent approval are not actions of this endpoint; the app does them when a card advances into the client stage, or from the dashboard.",
                "operationId": "workflow_card_move",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Plain numeric card id.",
                                        "example": 512
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "`move`, `advance`, `convert`, `reassign` or `request_changes`. Case-insensitive.",
                                        "enum": [
                                            "move",
                                            "advance",
                                            "convert",
                                            "reassign",
                                            "request_changes"
                                        ],
                                        "example": "advance"
                                    },
                                    "to": {
                                        "type": "string",
                                        "description": "Required for `move`: a `stage_id` from the board, or the word `ideas`. Only open stages accept cards; a scheduled post cannot move back.",
                                        "example": "8"
                                    },
                                    "to_scheduled": {
                                        "type": "boolean",
                                        "description": "For `advance`: true to jump straight to the Scheduled column instead of the next stage. Requires the card to pass the schedule gates.",
                                        "default": "false",
                                        "example": false
                                    },
                                    "share_with_client": {
                                        "type": "boolean",
                                        "description": "For `convert`: whether the new post is shared with the client. Defaults to the workflow setting.",
                                        "example": false
                                    },
                                    "user_id": {
                                        "type": "string",
                                        "description": "Required for `reassign`: encrypted user id from `members[]`, or 0 to clear the assignee.",
                                        "example": "Sl7mN2vB4Q=="
                                    },
                                    "comment": {
                                        "type": "string",
                                        "description": "Required for `request_changes`: what the author should change. Added to the card's activity.",
                                        "example": "Please swap the hero image for the approved one."
                                    },
                                    "return_stage_id": {
                                        "type": "integer",
                                        "description": "For `request_changes`: stage to send the card back to, from `return_stages` of `/api/workflow_card`. Defaults to `return_default_stage_id`.",
                                        "example": 7
                                    },
                                    "assignee_user_id": {
                                        "type": "string",
                                        "description": "For every action except `reassign`: encrypted user id to assign the card to where it lands.",
                                        "example": "Sl7mN2vB4Q=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. Picks the board owner; the card may be on any workspace of that board.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id",
                                    "action"
                                ],
                                "example": {
                                    "id": 512,
                                    "action": "advance"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "The app's confirmation for the action, normally `Moved`."
                                        },
                                        "card": {
                                            "type": "object",
                                            "description": "The card after the action, in the card shape of `/api/workflow_board`; null when the app returned no card."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Moved",
                                    "card": {
                                        "id": 512,
                                        "kind": "post",
                                        "workspace_id": "nX2k9Qp7Lw==",
                                        "column": "stage",
                                        "stage_id": 8,
                                        "title": "Launch teaser",
                                        "description": "Short teaser for the spring launch.",
                                        "platforms": [
                                            "facebook",
                                            "instagram"
                                        ],
                                        "account_ids": [
                                            "aB3cD4eF5g=="
                                        ],
                                        "target_date": "2026-11-01 15:00:00",
                                        "assignee": {
                                            "id": "Jd3xP0wQ1A==",
                                            "name": "Jane Doe"
                                        },
                                        "labels": [],
                                        "media": [
                                            {
                                                "url": "https://cdn.recurpost.com/media/12/teaser.jpg",
                                                "type": "image"
                                            }
                                        ],
                                        "status": "pending_review",
                                        "client_approval": true,
                                        "urgent": false,
                                        "source": "team",
                                        "schedule": {
                                            "count": 1,
                                            "first_at": "2026-11-01 15:30:00"
                                        },
                                        "post_id": 0,
                                        "created_by": {
                                            "id": "Jd3xP0wQ1A==",
                                            "name": "Jane Doe"
                                        },
                                        "created_at": "2026-10-01 10:00:00",
                                        "updated_at": "2026-10-22 09:40:00"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id or action is missing.)\n\naction must be move, advance, convert, reassign or request_changes. (action is another word.)\n\nA comment for the author is required to request changes. (action is request_changes and comment is blank.)\n\nto must be a stage_id or ideas. (action is move and to is neither a positive integer nor ideas.)\n\nuser_id is required to reassign (0 clears the assignee). (action is reassign and user_id is absent.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nThis workspace is not on the board. (workspace_id names a workspace of this owner that is not part of their board.)\n\nCards can only be dragged into open stages. (move targets a stage that is not open.)\n\nA scheduled post can't move back to a stage. Edit or delete it instead. (move on a card already in Scheduled.)\n\nThe Ideas stage is disabled in this workflow. (move to ideas while Ideas is switched off.)\n\nOnly ideas can be turned into posts. (convert on a card that is already a post.)\n\nNo workflow configured. (advance or convert before the owner set up a workflow.)\n\nThis card is already at the final stage. (advance on a card in the last column.)\n\nThis workflow has no Scheduled column. (advance with to_scheduled when the workflow cannot schedule.)\n\nThis post needs client approval before it can be scheduled. (advance to Scheduled on a client-shared card the client has not approved.)\n\nSelect at least one social account for this post. (A gate failed: the card has no accounts. A missing caption or media gives a similar message.)\n\nYour workflow has no writing stage to send this back to. (request_changes with no stage to return to.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "You are not a member of any workspace on this board. (The owner has no workspace you are an active member of.)\n\nYou don't have permission to do that. (Your role may not take this action on the card. The app may send a longer text naming the permission to ask the owner for, or \"You can only move ideas into your own stage.\".)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nCard not found. (No card with this id sits on a workspace of the board.)\n\nStage not found. (move targets a stage id that is not in the workflow.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This post is no longer waiting there - it is already with the client for approval. ... (The card moved on since you read it; refresh with /api/workflow_card. Other moved-on cases use their own 409 text.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The action failed inside the app without a message.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workflow_card_comment": {
            "post": {
                "tags": [
                    "Workflow Board"
                ],
                "summary": "Add a comment to a card's activity, optionally as an internal note.",
                "description": "Adds a comment to the card's activity log. With `internal` true the comment is an internal note that the client never sees on the shared calendar.",
                "operationId": "workflow_card_comment",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Plain numeric card id.",
                                        "example": 512
                                    },
                                    "text": {
                                        "type": "string",
                                        "description": "Comment text.",
                                        "example": "Client confirmed the launch date by phone."
                                    },
                                    "internal": {
                                        "type": "boolean",
                                        "description": "true to keep the comment from the client's view.",
                                        "default": "false",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. Picks the board owner; the card may be on any workspace of that board.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id",
                                    "text"
                                ],
                                "example": {
                                    "id": 512,
                                    "text": "Client confirmed the launch date by phone."
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Comment added`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Comment added"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or text is blank.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nThis workspace is not on the board. (workspace_id names a workspace of this owner that is not part of their board.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "You are not a member of any workspace on this board. (The owner has no workspace you are an active member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nCard not found. (No card with this id sits on a workspace of the board.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The comment could not be stored.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workflow_card_delete": {
            "post": {
                "tags": [
                    "Workflow Board"
                ],
                "summary": "Delete a card from the board.",
                "description": "Deletes the card. Your role needs the delete permission for the card (own or others' cards, as configured by the owner). Queue posts the card created that are still waiting to publish are retired with it; posts already published stay in history.",
                "operationId": "workflow_card_delete",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Plain numeric card id.",
                                        "example": 512
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. Picks the board owner; the card may be on any workspace of that board.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 512
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Card deleted`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Card deleted"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or not a positive integer.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nThis workspace is not on the board. (workspace_id names a workspace of this owner that is not part of their board.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "You are not a member of any workspace on this board. (The owner has no workspace you are an active member of.)\n\nTo delete this post, please ask your workspace owner to give you the \"...\" permission ... (Your role may not delete this card; the full text names the permission (delete others' posts, delete own posts, or approve on behalf for cards past the publish line).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nCard not found. (No card with this id sits on a workspace of the board.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The delete failed inside the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workflow_urgent": {
            "post": {
                "tags": [
                    "Workflow Board"
                ],
                "summary": "Send the client an urgent approval email for a card that is with them.",
                "description": "Mails the client an urgent approval request for one card: the email carries Approve and Request changes buttons that open the workspace's client calendar. The card must already be in the client review stage. `client_email` names the recipient; without it the workspace's default client email is used, and `save_as_default` stores the address you send as that default.\nYou act as yourself on the owner's board: your role needs the `send-client` permission (Send posts to clients), and the workspace needs a published client calendar.\n\nSends email every time: Each successful call mails the client again and marks the card urgent. There is no cooldown; the card stays `urgent` until the client decides.\n\nDefault client email: The default address is the workspace's `client_email` (see `/api/workspace_details`); `/api/workspace_update` sets it without sending anything.",
                "operationId": "workflow_urgent",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "card_id": {
                                        "type": "integer",
                                        "description": "Plain numeric card id from `/api/workflow_board`.",
                                        "example": 512
                                    },
                                    "client_email": {
                                        "type": "string",
                                        "format": "email",
                                        "description": "Address to mail. Left out, the workspace's default client email is used and the call fails when none is set.",
                                        "example": "client@example.com"
                                    },
                                    "save_as_default": {
                                        "type": "boolean",
                                        "description": "With `client_email`: `true` also stores the address as the workspace's default client email.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. Decides whose board the card is looked up on.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "card_id"
                                ],
                                "example": {
                                    "card_id": 512
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "The app's confirmation, `Urgent approval email sent to client@example.com.` with the address used."
                                        },
                                        "card": {
                                            "type": "object",
                                            "description": "The card in the card shape of `/api/workflow_board`, with `urgent` `true`; `null` when the app returned no card."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Urgent approval email sent to client@example.com.",
                                    "card": {
                                        "id": 512,
                                        "kind": "post",
                                        "workspace_id": "nX2k9Qp7Lw==",
                                        "column": "stage",
                                        "stage_id": 8,
                                        "title": "Launch teaser",
                                        "description": "Short teaser for the spring launch.",
                                        "platforms": [
                                            "facebook",
                                            "instagram"
                                        ],
                                        "account_ids": [
                                            "aB3cD4eF5g=="
                                        ],
                                        "target_date": "2026-11-01 15:00:00",
                                        "assignee": {
                                            "id": "Sl7mN2vB4Q==",
                                            "name": "Sam Lee"
                                        },
                                        "labels": [],
                                        "media": [
                                            {
                                                "url": "https://cdn.recurpost.com/media/12/teaser.jpg",
                                                "type": "image"
                                            }
                                        ],
                                        "status": "open",
                                        "client_approval": true,
                                        "urgent": true,
                                        "source": "team",
                                        "schedule": {
                                            "count": 1,
                                            "first_at": "2026-11-01 15:30:00"
                                        },
                                        "post_id": 0,
                                        "created_by": {
                                            "id": "Jd3xP0wQ1A==",
                                            "name": "Jane Doe"
                                        },
                                        "created_at": "2026-10-22 09:12:00",
                                        "updated_at": "2026-10-23 08:40:00"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nThis workspace is not on the board. (workspace_id names a workspace of this owner that is not part of their board.)\n\nclient_email must be a valid email address. (client_email is sent and is not an address.)\n\nThis post is not with the client yet - the urgent approval email goes out when it is handed over. (The card is not in the client review stage.)\n\nAdd the client email address the urgent approval should go to. (No client_email was sent and the workspace has no default client email.)\n\nPublish a Shareable Calendar for this workspace first - the urgent approval email's Approve and Request changes buttons have nowhere to send the client without it. (The workspace has no client calendar; create one with /api/shared_calendar.)\n\nCould not send the approval email. Please try again. (The mail could not be queued.)\n\nSomething went wrong (Other app-side refusals are relayed with their own text.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "You are not a member of any workspace on this board. (The owner has no workspace you are an active member of.)\n\nYou are no longer a member of this workspace. Refresh the page to see your current boards. (The app no longer finds your seat in the card's workspace.)\n\nTo request urgent approval, please ask your workspace owner to give you the \"Send posts to clients\" permission. (Your role lacks the send-client permission.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nCard not found. (card_id is missing or names no card on a workspace of the board.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workflow_client_decision": {
            "post": {
                "tags": [
                    "Workflow Board"
                ],
                "summary": "Record a client's approve, reject or comment on a card, for integrations that collect the client's answer elsewhere.",
                "description": "Writes the client's answer on a card the way the client calendar does, with `client_name` as the actor. `approve` applies to a card in the client review stage: the card's draft schedule becomes real posts and the card moves on, exactly as when the client approves on the calendar. `reject` applies to the client stage or to a card already sent back for changes, and needs `feedback` of at least 10 characters, which the team sees word for word. `comment` adds the feedback to the thread and moves nothing.\nThe app runs its own gates: a card with no schedule times, a schedule already in the past, or a card the client cannot see answers 400 with the app's wording; a decision already recorded answers 409. The app records the decision as made through the client calendar.",
                "operationId": "workflow_client_decision",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "card_id": {
                                        "type": "integer",
                                        "description": "Plain card id from `/api/workflow_board`.",
                                        "example": 184
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "`approve`, `reject` or `comment`.",
                                        "enum": [
                                            "approve",
                                            "reject",
                                            "comment"
                                        ],
                                        "example": "approve"
                                    },
                                    "feedback": {
                                        "type": "string",
                                        "description": "The client's words. Required for reject and comment, at least 10 characters.",
                                        "example": "Please use the blue version of the logo."
                                    },
                                    "client_name": {
                                        "type": "string",
                                        "description": "Name shown as the actor in the card's activity, up to 100 characters; markup is stripped. The app shows `Client` when empty.",
                                        "example": "Acme Marketing"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. The card must sit on one of the boards the caller sees.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "card_id",
                                    "action"
                                ],
                                "example": {
                                    "card_id": 184,
                                    "action": "approve"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "The app's confirmation."
                                        },
                                        "card_id": {
                                            "type": "integer",
                                            "description": "The card."
                                        },
                                        "action": {
                                            "type": "string",
                                            "description": "The action as sent."
                                        },
                                        "warning": {
                                            "type": "string",
                                            "description": "A note from the app when part of the work did not happen (for example the schedule could not be created), empty otherwise."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Approved. The posts are scheduled.",
                                    "card_id": 184,
                                    "action": "approve",
                                    "warning": ""
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (card_id is missing.)\n\naction must be approve, reject or comment. (action is another word.)\n\nfeedback needs at least 10 characters for reject and comment. (reject or comment with short or no feedback.)\n\nclient_name may have at most 100 characters. (client_name is longer.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\n<the app's reason> (The app refused: no schedule times yet, a schedule already in the past, or a card the client cannot see.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "You are not a member of any workspace on this board. (The owner has no workspace you are an active member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nCard not found. (card_id is missing or names no card on a workspace of the board.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "<the app's warning> (Nothing was recorded, for example the same decision was already recorded.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workflow_settings": {
            "post": {
                "tags": [
                    "Workflow Settings"
                ],
                "summary": "Read the workflow with its stages, create it, change its switches or toggle the Ideas stage.",
                "description": "With `action=get` (the default) returns the workflow and its stages, or `workflow` `null` with no stages when the account has none yet. `create` builds the workflow from a `template`: `blank` gives an empty board to add stages to with `/api/workflow_stage`, `standard` gives RecurPost's stock stages. `settings` changes any of the four switches; the ones left out keep their value. `ideas` switches the Ideas column on or off with `enabled`.\nEvery write answers with the workflow as it stands afterwards. Owner only.\n\nSwitches are merged for you: The app's own settings call switches off whatever it is not told about; this endpoint fills the switches you leave out with their current values, so a single-switch change is safe.\n\nOne workflow per account: There is no delete. A created workflow stays; reshape it with `/api/workflow_stage`.",
                "operationId": "workflow_settings",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "`get`, `create`, `settings` or `ideas`. Case does not matter.",
                                        "enum": [
                                            "get",
                                            "create",
                                            "settings",
                                            "ideas"
                                        ],
                                        "default": "get",
                                        "example": "settings"
                                    },
                                    "template": {
                                        "type": "string",
                                        "description": "With `create`: `blank` or `standard`.",
                                        "enum": [
                                            "blank",
                                            "standard"
                                        ],
                                        "default": "blank",
                                        "example": "standard"
                                    },
                                    "require_approval_on_all_posts": {
                                        "type": "boolean",
                                        "description": "With `settings`: every post needs client approval before it is scheduled. At least one of the four switches must be sent.",
                                        "example": true
                                    },
                                    "show_ideas_to_client": {
                                        "type": "boolean",
                                        "description": "With `settings`: the client sees the Ideas column on the client calendar.",
                                        "example": false
                                    },
                                    "request_approval_on_ideas": {
                                        "type": "boolean",
                                        "description": "With `settings`: ideas are sent to the client for approval too.",
                                        "example": false
                                    },
                                    "allow_clients_to_suggest_ideas": {
                                        "type": "boolean",
                                        "description": "With `settings`: clients may add ideas from the client calendar.",
                                        "example": true
                                    },
                                    "enabled": {
                                        "type": "boolean",
                                        "description": "Required when `action` is `ideas`: `true` shows the Ideas column, `false` hides it.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. The workflow is account-wide; the workspace must be yours.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success` on get, `Workflow created.`, `Settings saved.` or `Ideas stage updated.`"
                                        },
                                        "workflow": {
                                            "type": "object",
                                            "description": "The workflow, or `null` when the account has none.",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "Plain workflow id."
                                                },
                                                "ideas_enabled": {
                                                    "type": "boolean",
                                                    "description": "Whether the Ideas column is shown."
                                                },
                                                "require_approval_on_all_posts": {
                                                    "type": "boolean",
                                                    "description": "The switch of the same name."
                                                },
                                                "show_ideas_to_client": {
                                                    "type": "boolean",
                                                    "description": "The switch of the same name."
                                                },
                                                "request_approval_on_ideas": {
                                                    "type": "boolean",
                                                    "description": "The switch of the same name."
                                                },
                                                "allow_clients_to_suggest_ideas": {
                                                    "type": "boolean",
                                                    "description": "The switch of the same name."
                                                }
                                            }
                                        },
                                        "stages": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain stage id, the `stage_id` of `/api/workflow_stage` and `/api/workflow_card_save`."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Stage name."
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "description": "`work`, `review` or `client` (the client review stage)."
                                                    },
                                                    "color": {
                                                        "type": "string",
                                                        "description": "`blue`, `orange`, `teal`, `green`, `purple`, `red`, `yellow` or `pink`."
                                                    },
                                                    "position": {
                                                        "type": "integer",
                                                        "description": "Order on the board, 1 first."
                                                    },
                                                    "timeout_hours": {
                                                        "type": "integer",
                                                        "description": "Hours a card may sit in the stage before the timeout policy runs; 0 for no timeout."
                                                    },
                                                    "timeout_policy": {
                                                        "type": "string",
                                                        "description": "`hold`, `auto_approve`, `escalate` or `reschedule`; empty when there is no timeout."
                                                    },
                                                    "reschedule_by_days": {
                                                        "type": "integer",
                                                        "description": "Days the `reschedule` policy pushes the post by."
                                                    },
                                                    "reject_to_stage_id": {
                                                        "type": "integer",
                                                        "description": "On the client stage: the stage a rejected post returns to; 0 when unset."
                                                    },
                                                    "locked": {
                                                        "type": "boolean",
                                                        "description": "`true` for a stage the builder does not let you remove or move."
                                                    },
                                                    "cards": {
                                                        "type": "integer",
                                                        "description": "Cards currently in the stage."
                                                    },
                                                    "roles": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "object",
                                                            "properties": {
                                                                "id": {
                                                                    "type": "integer",
                                                                    "description": "Plain id of a role that works the stage."
                                                                },
                                                                "name": {
                                                                    "type": "string",
                                                                    "description": "That role's name."
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Settings saved.",
                                    "workflow": {
                                        "id": 9,
                                        "ideas_enabled": true,
                                        "require_approval_on_all_posts": true,
                                        "show_ideas_to_client": false,
                                        "request_approval_on_ideas": true,
                                        "allow_clients_to_suggest_ideas": false
                                    },
                                    "stages": [
                                        {
                                            "id": 71,
                                            "name": "Writing",
                                            "type": "work",
                                            "color": "blue",
                                            "position": 1,
                                            "timeout_hours": 0,
                                            "timeout_policy": "",
                                            "reschedule_by_days": 0,
                                            "reject_to_stage_id": 0,
                                            "locked": false,
                                            "cards": 2,
                                            "roles": [
                                                {
                                                    "id": 3,
                                                    "name": "Writer"
                                                }
                                            ]
                                        },
                                        {
                                            "id": 72,
                                            "name": "Client Review",
                                            "type": "client",
                                            "color": "purple",
                                            "position": 2,
                                            "timeout_hours": 48,
                                            "timeout_policy": "reschedule",
                                            "reschedule_by_days": 1,
                                            "reject_to_stage_id": 71,
                                            "locked": true,
                                            "cards": 0,
                                            "roles": []
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\naction must be get, create, settings or ideas. (action is another word.)\n\ntemplate must be blank or standard. (create with another template.)\n\nSend at least one of require_approval_on_all_posts, show_ideas_to_client, request_approval_on_ideas, allow_clients_to_suggest_ideas. (settings with none of the four switches.)\n\nenabled is required with action ideas. (ideas without enabled.)\n\nSomething went wrong (The app refused; its own text is relayed when it sent one, for example `Failed to create workflow. Please try again.`)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can change the workflow. (The workspace, and so the account, belongs to someone else. Applies to get as well.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nThis account has no workflow yet; create one first. (settings or ideas before a workflow exists.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This account has a workflow already. (create when a workflow exists.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/workflow_stage": {
            "post": {
                "tags": [
                    "Workflow Settings"
                ],
                "summary": "Add a stage, change one or delete one.",
                "description": "With `action=save` (the default) adds a stage when `stage_id` is absent and changes that stage when it is given; on a change the fields left out keep their value. With `action=delete` removes the stage named by `stage_id`, which needs `confirm=true` and is refused while cards sit in the stage.\nA `client` stage is the client review stage: only one is allowed, it must be the last stage before Scheduled, it takes no roles, and it is the only stage where the `reschedule` timeout policy and `reject_to_stage_id` apply. Every call answers with the full stage list afterwards. Owner only.\n\nChanging the type clears the roles: Turning a stage into a `client` stage drops its roles. Turning a client stage into a work or review stage keeps the `reschedule` policy only if you also send another `timeout_policy`; otherwise the call is refused.\n\nPosition: Positions are re-numbered by the app after a save, so read them back from `stages[]` rather than assuming the one you sent.",
                "operationId": "workflow_stage",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "`save` or `delete`. Case does not matter.",
                                        "enum": [
                                            "save",
                                            "delete"
                                        ],
                                        "default": "save",
                                        "example": "save"
                                    },
                                    "stage_id": {
                                        "type": "integer",
                                        "description": "Plain stage id from `stages[].id` of `/api/workflow_settings`. Required with `delete`; with `save` names the stage to change, omit it to add one.",
                                        "example": 71
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "Required when adding: stage name, 1 to 60 characters.",
                                        "example": "Review"
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "Required when adding: `work`, `review` or `client`.",
                                        "enum": [
                                            "work",
                                            "review",
                                            "client"
                                        ],
                                        "example": "review"
                                    },
                                    "color": {
                                        "type": "string",
                                        "description": "`blue`, `orange`, `teal`, `green`, `purple`, `red`, `yellow` or `pink`.",
                                        "enum": [
                                            "blue",
                                            "orange",
                                            "teal",
                                            "green",
                                            "purple",
                                            "red",
                                            "yellow",
                                            "pink"
                                        ],
                                        "default": "blue",
                                        "example": "orange"
                                    },
                                    "position": {
                                        "type": "integer",
                                        "description": "Place in the board order, 1 first. Defaults to 1 when adding and to the current place on a change.",
                                        "example": 2
                                    },
                                    "timeout_hours": {
                                        "type": "integer",
                                        "description": "Hours before the timeout policy runs: 0 for none, or one of 4, 8, 24, 48, 72, 168.",
                                        "enum": [
                                            0,
                                            4,
                                            8,
                                            24,
                                            48,
                                            72,
                                            168
                                        ],
                                        "default": "0",
                                        "example": 48
                                    },
                                    "timeout_policy": {
                                        "type": "string",
                                        "description": "What happens when the timeout passes: `hold`, `auto_approve`, `escalate`, or `reschedule` on the client stage only. Read only when `timeout_hours` is not 0.",
                                        "enum": [
                                            "hold",
                                            "auto_approve",
                                            "escalate",
                                            "reschedule"
                                        ],
                                        "default": "hold",
                                        "example": "escalate"
                                    },
                                    "reschedule_by_days": {
                                        "type": "integer",
                                        "description": "With the `reschedule` policy: how many days the post is pushed by, 1 to 30.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "reject_to_stage_id": {
                                        "type": "integer",
                                        "description": "On the client stage: the stage a post the client rejects goes back to.",
                                        "example": 71
                                    },
                                    "roles": {
                                        "type": "array",
                                        "items": [],
                                        "description": "The roles that work the stage, as role ids or names (array or comma-separated), from `/api/roles`. Replaces the current roles; ignored on a `client` stage, which has none.",
                                        "example": [
                                            "Editor"
                                        ]
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Required when `action` is `delete`: must be `true`.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. The workflow is account-wide; the workspace must be yours.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Stage added.`, `Stage updated.` or `Stage deleted.`"
                                        },
                                        "stage_id": {
                                            "type": "integer",
                                            "description": "Plain id of the stage added or changed; `null` after a delete."
                                        },
                                        "stages": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "description": "Every stage of the workflow after the change, in the shape of `stages[]` of `/api/workflow_settings`."
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Stage added.",
                                    "stage_id": 73,
                                    "stages": [
                                        {
                                            "id": 71,
                                            "name": "Writing",
                                            "type": "work",
                                            "color": "blue",
                                            "position": 1,
                                            "timeout_hours": 0,
                                            "timeout_policy": "",
                                            "reschedule_by_days": 0,
                                            "reject_to_stage_id": 0,
                                            "locked": false,
                                            "cards": 2,
                                            "roles": [
                                                {
                                                    "id": 3,
                                                    "name": "Writer"
                                                }
                                            ]
                                        },
                                        {
                                            "id": 73,
                                            "name": "Review",
                                            "type": "review",
                                            "color": "orange",
                                            "position": 2,
                                            "timeout_hours": 48,
                                            "timeout_policy": "escalate",
                                            "reschedule_by_days": 1,
                                            "reject_to_stage_id": 0,
                                            "locked": false,
                                            "cards": 0,
                                            "roles": [
                                                {
                                                    "id": 5,
                                                    "name": "Editor"
                                                }
                                            ]
                                        },
                                        {
                                            "id": 72,
                                            "name": "Client Review",
                                            "type": "client",
                                            "color": "purple",
                                            "position": 3,
                                            "timeout_hours": 48,
                                            "timeout_policy": "reschedule",
                                            "reschedule_by_days": 1,
                                            "reject_to_stage_id": 71,
                                            "locked": true,
                                            "cards": 0,
                                            "roles": []
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\naction must be save or delete. (action is another word.)\n\nstage_id is required. (delete without stage_id.)\n\nSend confirm=true to delete the stage. (delete without confirm=true.)\n\nname must be 1 to 60 characters. (Adding without a name, or a blank or too long name.)\n\ntype must be work, review or client. (Adding without a type, or another type.)\n\ncolor must be one of blue, orange, teal, green, purple, red, yellow, pink. (color is another word.)\n\ntimeout_hours must be 0 (none) or one of 4, 8, 24, 48, 72, 168. (timeout_hours is another number.)\n\ntimeout_policy must be hold, auto_approve or escalate, or reschedule on the client stage. (A timeout is set with another policy, or reschedule on a work or review stage.)\n\nreschedule_by_days must be 1 to 30. (The reschedule policy with a day count outside 1 to 30.)\n\nSomething went wrong (The app refused; its own text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can change the workflow. (The workspace, and so the account, belongs to someone else.)\n\nThis stage has 2 posts on the board. Move them to another stage before deleting it. (delete while cards sit in the stage; the number is the card count.)\n\nOnly one Client Review stage is allowed per workflow. (Adding a second client stage.)\n\nClient Review must be the last stage before Scheduled. (The client stage would not be last in the order.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nThis account has no workflow yet; create one first. (No workflow exists; create it with /api/workflow_settings.)\n\nstage_id is not a stage of this workflow. (stage_id is positive but names no stage of the workflow.)\n\nRole 'X' is not one of this account's roles; see roles. (A value in roles matches no role id or name.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/shared_calendar": {
            "post": {
                "tags": [
                    "Shared Calendars"
                ],
                "summary": "Read, create, change, link, delete the workspace's client calendar, or manage the people on it.",
                "description": "One endpoint for the workspace's client calendar, chosen with `action`:\n- `get` (the default): the calendar, or `calendar` `null` when none exists. Any member may read.\n- `create`: a new calendar from `name`, `start_date` and either `end_date` or `never_expires`, with optional `comments_allowed` and `pin`.\n- `update`: the same fields over the current ones; fields left out keep their value, `pin` sent empty removes the PIN.\n- `link`: switches the public link on or off with `enabled`.\n- `delete`: removes the calendar with its people and comments, `confirm=true` required.\n- `clients`: lists the people on the calendar.\n- `invite_client`: mails the calendar link to `email` and adds them.\n- `remove_client`: takes the person named by `client_id` off.\n\nEvery action but `get` needs the workspace owner's own key.\n\nThe link counts against the plan: A calendar can exist with its link off. Switching the link on (action `link`) uses one of the plan's shareable calendar slots and is refused with 403 when none is left; a calendar created here starts with the link on only if the plan allows it.\n\nInvitations send mail: `invite_client` mails the link at once. The owner and the members already on the calendar appear in `people` with their type; only people of type `client` are what the invite adds.",
                "operationId": "shared_calendar",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "`get`, `create`, `update`, `link`, `delete`, `clients`, `invite_client` or `remove_client`. Case does not matter.",
                                        "enum": [
                                            "get",
                                            "create",
                                            "update",
                                            "link",
                                            "delete",
                                            "clients",
                                            "invite_client",
                                            "remove_client"
                                        ],
                                        "default": "get",
                                        "example": "create"
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "Required when `action` is `create`: the calendar's name, 1 to 100 characters. Optional on `update`.",
                                        "example": "Acme client calendar"
                                    },
                                    "start_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Required when `action` is `create`: first day the client sees, `YYYY-MM-DD`. Optional on `update`.",
                                        "example": "2026-11-01"
                                    },
                                    "end_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Last day the client sees, `YYYY-MM-DD`, on or after `start_date`. Required on `create` unless `never_expires` is `true`.",
                                        "example": "2026-12-31"
                                    },
                                    "never_expires": {
                                        "type": "boolean",
                                        "description": "`true` keeps the calendar open with no end date; `end_date` is then ignored.",
                                        "example": false
                                    },
                                    "comments_allowed": {
                                        "type": "boolean",
                                        "description": "Whether the client may comment on posts. Defaults to `false` on create.",
                                        "example": true
                                    },
                                    "pin": {
                                        "type": "string",
                                        "description": "A 4-digit PIN the client must enter to open the calendar. Send an empty string on `update` to remove it.",
                                        "example": "1234"
                                    },
                                    "enabled": {
                                        "type": "boolean",
                                        "description": "Required when `action` is `link`: `true` makes the public link work, `false` switches it off.",
                                        "example": true
                                    },
                                    "email": {
                                        "type": "string",
                                        "format": "email",
                                        "description": "Required when `action` is `invite_client`: the address to mail the calendar link to.",
                                        "example": "client@example.com"
                                    },
                                    "client_id": {
                                        "type": "integer",
                                        "description": "Required when `action` is `remove_client`: plain id from `people[].id` of action `clients`.",
                                        "example": 88
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Required when `action` is `delete`: must be `true`.",
                                        "example": true
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success` on get and clients, `Client calendar created.`, `Client calendar updated.`, `Calendar link enabled.` or `Calendar link disabled.`, `Client calendar deleted.`, `Invitation sent.`, `Person removed.`"
                                        },
                                        "calendar": {
                                            "type": "object",
                                            "description": "The calendar, or `null` when the workspace has none. Absent after a delete.",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted calendar id."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Calendar name."
                                                },
                                                "url": {
                                                    "type": "string",
                                                    "format": "uri",
                                                    "description": "The public link the client opens."
                                                },
                                                "start_date": {
                                                    "type": "string",
                                                    "format": "date",
                                                    "description": "First day shown."
                                                },
                                                "end_date": {
                                                    "type": "string",
                                                    "format": "date",
                                                    "description": "Last day shown; empty when `never_expires` is true."
                                                },
                                                "never_expires": {
                                                    "type": "boolean",
                                                    "description": "`true` when the calendar has no end date."
                                                },
                                                "comments_allowed": {
                                                    "type": "boolean",
                                                    "description": "Whether the client may comment."
                                                },
                                                "has_pin": {
                                                    "type": "boolean",
                                                    "description": "`true` when a PIN is set. The PIN itself is never returned."
                                                },
                                                "link_enabled": {
                                                    "type": "boolean",
                                                    "description": "Whether the public link currently works."
                                                },
                                                "created_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "description": "When the calendar was created, UTC."
                                                }
                                            }
                                        },
                                        "people": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain id of a person on the calendar, the `client_id` of remove_client. Only with clients, invite_client and remove_client."
                                                    },
                                                    "email": {
                                                        "type": "string",
                                                        "format": "email",
                                                        "description": "Their address."
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "description": "`owner`, `member` or `client`."
                                                    },
                                                    "mail_enabled": {
                                                        "type": "boolean",
                                                        "description": "Whether calendar mails go to this person."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Invitation sent.",
                                    "calendar": {
                                        "id": "cA7lE9nD2r==",
                                        "name": "Acme client calendar",
                                        "url": "https://app.recurpost.com/calendar/7f3a9c1e2b",
                                        "start_date": "2026-11-01",
                                        "end_date": "",
                                        "never_expires": true,
                                        "comments_allowed": true,
                                        "has_pin": true,
                                        "link_enabled": true,
                                        "created_at": "2026-10-20 08:00:00"
                                    },
                                    "people": [
                                        {
                                            "id": 61,
                                            "email": "jane@agency.example",
                                            "type": "owner",
                                            "mail_enabled": true
                                        },
                                        {
                                            "id": 88,
                                            "email": "client@example.com",
                                            "type": "client",
                                            "mail_enabled": true
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\naction must be one of get, create, update, link, delete, clients, invite_client, remove_client. (action is another word.)\n\nname must be 1 to 100 characters. (create without a name, or a blank or too long name.)\n\nstart_date and end_date must be YYYY-MM-DD with end_date on or after start_date, or send never_expires=true. (A date is missing or malformed, or end_date is before start_date without never_expires.)\n\npin must be exactly 4 digits, or blank to remove it. (pin is set and is not four digits.)\n\nenabled is required with action link. (link without enabled.)\n\nSend confirm=true to delete the client calendar with its clients and comments. (delete without confirm=true.)\n\nemail must be a valid email address. (invite_client without a valid address.)\n\nSomething went wrong (The app refused; its own text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can manage the client calendar. (Any action but get with a key that is not the workspace owner's.)\n\nShareable calendar limit over. (Enabling the link would exceed the plan's calendar allowance; without any allowance the text is the same. The app's wording is relayed, `Your plan allows no more calendar links.` when it sent none.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nThis workspace has no client calendar yet; create one first. (Any action but get or create while the workspace has no calendar.)\n\nclient_id is not a person on this calendar; see action clients. (remove_client with an id that is not on this workspace's calendar.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This workspace already has a client calendar; use action update. (create when a calendar exists.)\n\nCalendar is already shared with the same email. (invite_client with an address already on the calendar.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/shared_calendar_comments": {
            "post": {
                "tags": [
                    "Shared Calendars"
                ],
                "summary": "List, add or mark as read the client calendar comments on a queued post.",
                "description": "The comments on one queued post as they appear on the client calendar: what the client wrote from the calendar page and what the team answered. With `action=list` (the default) reads them, 6 per `page`, newest first. `add` writes a comment in your name. `mark` sets the unread flag of the post's comments, or of one comment with `comment_id`, and answers with the list afterwards.\nAny active member of the workspace may call this; adding and marking need the workspace to have a client calendar.\n\nWho is listed: Without a client calendar the list still answers, with whatever the team wrote before; the client can only comment through a calendar whose `comments_allowed` is on.\n\nYour name on the comment: A comment added here carries the name on your RecurPost account and `from_client` false; a comment the client leaves on the calendar page carries the name they typed there.",
                "operationId": "shared_calendar_comments",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "post_id": {
                                        "type": "integer",
                                        "description": "Plain post id, `items[].post_id` of `/api/queue_list` (the id shared by the queue items of one post).",
                                        "example": 48213
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "`list`, `add` or `mark`. Case does not matter.",
                                        "enum": [
                                            "list",
                                            "add",
                                            "mark"
                                        ],
                                        "default": "list",
                                        "example": "add"
                                    },
                                    "comment": {
                                        "type": "string",
                                        "description": "Required when `action` is `add`: the comment, 1 to 2000 characters. Surrounding spaces are trimmed.",
                                        "example": "Thanks, we will swap the image."
                                    },
                                    "read": {
                                        "type": "boolean",
                                        "description": "Required when `action` is `mark`: `true` marks as read, `false` as unread.",
                                        "example": true
                                    },
                                    "comment_id": {
                                        "type": "integer",
                                        "description": "With `mark`: plain id of one comment from `comments[].id`. Left out, every comment of the post is marked.",
                                        "example": 7
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Page of the list, 6 comments per page.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. When sent, the post must be in this workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "post_id"
                                ],
                                "example": {
                                    "post_id": 48213
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success` on list, `Comment added.`, `Comments marked.`"
                                        },
                                        "page": {
                                            "type": "integer",
                                            "description": "The page returned. list and mark only."
                                        },
                                        "comments": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain comment id, the `comment_id` of mark. list and mark only."
                                                    },
                                                    "author": {
                                                        "type": "string",
                                                        "description": "Name the comment was written under."
                                                    },
                                                    "from_client": {
                                                        "type": "boolean",
                                                        "description": "`true` when the client wrote it from the calendar page, `false` for a team member."
                                                    },
                                                    "comment": {
                                                        "type": "string",
                                                        "description": "The comment."
                                                    },
                                                    "unread": {
                                                        "type": "boolean",
                                                        "description": "`true` while the comment is unread."
                                                    },
                                                    "created_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When it was written, UTC."
                                                    }
                                                }
                                            }
                                        },
                                        "comment": {
                                            "type": "object",
                                            "description": "After `add`: the new comment alone, in the same shape as a `comments[]` item."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "page": 1,
                                    "comments": [
                                        {
                                            "id": 8,
                                            "author": "Jane Doe",
                                            "from_client": false,
                                            "comment": "Thanks, we will swap the image.",
                                            "unread": false,
                                            "created_at": "2026-10-21 10:00:00"
                                        },
                                        {
                                            "id": 7,
                                            "author": "Client A",
                                            "from_client": true,
                                            "comment": "Love it, but can we use the other photo?",
                                            "unread": true,
                                            "created_at": "2026-10-20 10:00:00"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\naction must be list, add or mark. (action is another word.)\n\ncomment must be 1 to 2000 characters. (add with a blank or too long comment.)\n\nread is required with action mark. (mark without read.)\n\nSomething went wrong (The app refused; its own text is relayed when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\npost_id is not a post of this workspace. (post_id is missing, is not the workspace owner's, or is outside the named workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This workspace has no client calendar, so there is nowhere to comment. (add while the workspace has no calendar.)\n\nThis workspace has no client calendar. (mark while the workspace has no calendar.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_accounts": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "Social accounts of the workspace that have an inbox, with their to-review counts and last sync time.",
                "description": "Lists the accounts of the workspace the inbox covers: Facebook pages, LinkedIn company pages, Google Business locations and Instagram business accounts. Other networks (Twitter/X, Pinterest, TikTok, YouTube, Threads, Bluesky, personal profiles) have no inbox and are not listed. Use the returned `id` as `account_id` on the other inbox endpoints.\n\nTimezone: Every datetime in this module is shown in the workspace owner's timezone as `YYYY-MM-DD HH:MM:SS`.",
                "operationId": "inbox_accounts",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "accounts": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted social account id. Pass it as `account_id` on the other inbox endpoints."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Page, company, location or profile name."
                                                    },
                                                    "network": {
                                                        "type": "string",
                                                        "description": "`facebook`, `linkedin`, `google_my_business` or `instagram`."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "`active`, `paused` or `needs_reconnection`. Reads work on any status; replies, deletes, likes and syncs need `active` or `paused`."
                                                    },
                                                    "to_review_count": {
                                                        "type": "integer",
                                                        "description": "Items currently in status `to_review`."
                                                    },
                                                    "last_synced_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When the account was last synced, in the workspace owner's timezone; `null` when it has never been synced."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "accounts": [
                                        {
                                            "id": "aK3mZ8vQr1==",
                                            "name": "Acme Coffee",
                                            "network": "facebook",
                                            "status": "active",
                                            "to_review_count": 7,
                                            "last_synced_at": "2026-10-22 09:15:00"
                                        },
                                        {
                                            "id": "gB9xT4nWp2==",
                                            "name": "Acme Coffee - Downtown",
                                            "network": "google_my_business",
                                            "status": "active",
                                            "to_review_count": 2,
                                            "last_synced_at": null
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id is not a valid encrypted id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not a member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_list": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "One page of an account's inbox items, filtered by status, type, bookmark, labels and assignee, or a delta since a moment.",
                "description": "Returns the items of one account. An item is one inbox entry: a `comment` (a comment or mention on one of the account's posts, with the replies under it), a `message` (a direct message conversation with one person) or a `review` (one Google Business review). Items have a status: `to_review` (new, nobody has handled it), `assigned` (handed to a team member) or `reviewed` (done).\nWithout `updated_since` the list is one status at a time (`to_review` by default), newest activity first. With `updated_since` the filters are ignored and every item that arrived or received a new comment or message after that moment is returned, whatever its status, newest change first; poll it to read the delta instead of re-reading page 1.\nThe item shape documented here is the one returned by `/api/inbox_item` too; the other endpoints refer back to it.\n\nMessage items are lighter: A `message` item has no `post` and no `liked` field; it is a conversation, not a reaction to a post. Read its messages with `/api/inbox_conversation`.\n\nFirst read of a Google Business location: A Google Business location that has never been synced is pulled from Google once before its first listing, so the first call can take a few seconds.\n\nPolling with updated_since: Use `last_activity_at` of the newest item you already hold as the next `updated_since`; it is compared with a strict greater-than, so the item itself is not returned again. Items in any status come back, including ones you already reviewed, when they get new activity.",
                "operationId": "inbox_list",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted account id from `/api/inbox_accounts`. Must be a Facebook page, LinkedIn company page, Google Business location or Instagram business account of the workspace.",
                                        "example": "aK3mZ8vQr1=="
                                    },
                                    "status": {
                                        "type": "string",
                                        "description": "Which status to list. Ignored when `updated_since` is given.",
                                        "enum": [
                                            "to_review",
                                            "assigned",
                                            "reviewed"
                                        ],
                                        "default": "to_review",
                                        "example": "to_review"
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "Only items of this kind. Omit for every kind. Ignored when `updated_since` is given.",
                                        "enum": [
                                            "comment",
                                            "message",
                                            "review"
                                        ],
                                        "example": "comment"
                                    },
                                    "bookmarked": {
                                        "type": "boolean",
                                        "description": "`true` to return bookmarked items only. Ignored when `updated_since` is given.",
                                        "default": "false",
                                        "example": false
                                    },
                                    "label_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Plain integer label ids from `/api/inbox_label_list`, as an array or a comma-separated string. Returns items carrying any of them. Ignored when `updated_since` is given.",
                                        "example": [
                                            12,
                                            15
                                        ]
                                    },
                                    "assigned_to": {
                                        "type": "string",
                                        "description": "Encrypted user id from `/api/inbox_team_members`. Returns items assigned to that member. Ignored when `updated_since` is given.",
                                        "example": "MRBkPwJx4i8="
                                    },
                                    "order": {
                                        "type": "string",
                                        "description": "`oldest` puts the oldest activity first. Anything else is newest first. Ignored when `updated_since` is given.",
                                        "enum": [
                                            "newest",
                                            "oldest"
                                        ],
                                        "default": "newest",
                                        "example": "newest"
                                    },
                                    "updated_since": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "Return every item of the account that arrived or got a new comment or message after this moment, in any status, newest change first. Send an ISO 8601 value with an offset or `Z`, e.g. `2026-10-15T09:30:00+05:30`; a value without an offset is read as UTC. The value is echoed back as `updated_since`.",
                                        "example": "2026-10-21T09:30:00+00:00"
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Page number, starting at 1.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "per_page": {
                                        "type": "integer",
                                        "description": "Items per page, 1 to 50.",
                                        "default": "20",
                                        "example": 20
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "account_id"
                                ],
                                "example": {
                                    "account_id": "aK3mZ8vQr1=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "page": {
                                            "type": "integer",
                                            "description": "Page returned."
                                        },
                                        "per_page": {
                                            "type": "integer",
                                            "description": "Page size applied."
                                        },
                                        "updated_since": {
                                            "type": "string",
                                            "description": "The value you sent, echoed back. Only present on a delta read."
                                        },
                                        "items": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Item id (plain integer). This is the `id` the item endpoints take."
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "description": "`comment`, `message` or `review`."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "`to_review`, `assigned` or `reviewed`."
                                                    },
                                                    "bookmarked": {
                                                        "type": "boolean",
                                                        "description": "Bookmarked in RecurPost."
                                                    },
                                                    "liked": {
                                                        "type": "boolean",
                                                        "description": "Whether the account has liked the post of the item. Absent on `message` items."
                                                    },
                                                    "from": {
                                                        "type": "object",
                                                        "properties": {
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Display name of the person who commented, wrote or reviewed."
                                                            },
                                                            "username": {
                                                                "type": "string",
                                                                "description": "Their handle on the network, when the network gives one."
                                                            },
                                                            "image": {
                                                                "type": "string",
                                                                "description": "URL of their profile picture, or empty."
                                                            },
                                                            "network_user_id": {
                                                                "type": "string",
                                                                "description": "Their id on the network."
                                                            }
                                                        }
                                                    },
                                                    "latest": {
                                                        "type": "object",
                                                        "properties": {
                                                            "text": {
                                                                "type": "string",
                                                                "description": "Text of the comment that raised the item, or for a conversation the newest message."
                                                            },
                                                            "at": {
                                                                "type": "string",
                                                                "format": "date-time",
                                                                "description": "When that comment or message was written."
                                                            }
                                                        }
                                                    },
                                                    "post": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "description": "Id of the post on the network. For a review this is the Google review id. Absent on `message` items."
                                                            },
                                                            "type": {
                                                                "type": "string",
                                                                "description": "`text`, `image`, `video`, `carousel`, `document`, `link` or `review`."
                                                            },
                                                            "text": {
                                                                "type": "string",
                                                                "description": "Post text, or the review text."
                                                            },
                                                            "image": {
                                                                "type": "string",
                                                                "description": "First image URL of the post, or empty."
                                                            },
                                                            "video": {
                                                                "type": "string",
                                                                "description": "Video URL of the post, or empty."
                                                            },
                                                            "link": {
                                                                "type": "string",
                                                                "description": "Link the post shares, or empty."
                                                            },
                                                            "title": {
                                                                "type": "string",
                                                                "description": "Title of the shared link, or empty."
                                                            },
                                                            "permalink": {
                                                                "type": "string",
                                                                "description": "URL of the post on the network."
                                                            },
                                                            "likes": {
                                                                "type": "integer",
                                                                "description": "Like count of the post as last synced."
                                                            },
                                                            "comments": {
                                                                "type": "integer",
                                                                "description": "Comment count of the post as last synced."
                                                            },
                                                            "posted_at": {
                                                                "type": "string",
                                                                "format": "date-time",
                                                                "description": "When the post (or review) was published."
                                                            }
                                                        }
                                                    },
                                                    "labels": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "object",
                                                            "properties": {
                                                                "id": {
                                                                    "type": "integer",
                                                                    "description": "Label id (plain integer)."
                                                                },
                                                                "name": {
                                                                    "type": "string",
                                                                    "description": "Label name."
                                                                }
                                                            }
                                                        }
                                                    },
                                                    "assigned_to": {
                                                        "type": "object",
                                                        "description": "`{id, name}` of the team member the item is assigned to, or `null`. `id` is an encrypted user id."
                                                    },
                                                    "assigned_by": {
                                                        "type": "object",
                                                        "description": "`{id, name}` of who assigned it, or `null`."
                                                    },
                                                    "reviewed_by": {
                                                        "type": "string",
                                                        "description": "Name of who marked the item reviewed. `null` unless status is `reviewed`."
                                                    },
                                                    "last_activity_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When the item arrived or last received a comment or message. This is the clock `updated_since` compares against."
                                                    },
                                                    "rating": {
                                                        "type": "integer",
                                                        "description": "Star rating 1 to 5. Only present on `review` items."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "page": 1,
                                    "per_page": 20,
                                    "items": [
                                        {
                                            "id": 58213,
                                            "type": "comment",
                                            "status": "to_review",
                                            "bookmarked": false,
                                            "liked": false,
                                            "from": {
                                                "name": "Maria Lopez",
                                                "username": "maria.lopez",
                                                "image": "https://graph.facebook.com/10223/picture",
                                                "network_user_id": "10223344556677"
                                            },
                                            "latest": {
                                                "text": "Do you open on Sundays?",
                                                "at": "2026-10-22 08:42:10"
                                            },
                                            "post": {
                                                "id": "1234567890_987654321",
                                                "type": "image",
                                                "text": "New autumn blends are in.",
                                                "image": "https://scontent.example.com/autumn.jpg",
                                                "video": "",
                                                "link": "",
                                                "title": "",
                                                "permalink": "https://www.facebook.com/1234567890/posts/987654321",
                                                "likes": 41,
                                                "comments": 6,
                                                "posted_at": "2026-10-21 17:00:00"
                                            },
                                            "labels": [
                                                {
                                                    "id": 12,
                                                    "name": "Question"
                                                }
                                            ],
                                            "assigned_to": null,
                                            "assigned_by": null,
                                            "reviewed_by": null,
                                            "last_activity_at": "2026-10-22 08:42:10"
                                        },
                                        {
                                            "id": 58190,
                                            "type": "message",
                                            "status": "to_review",
                                            "bookmarked": true,
                                            "from": {
                                                "name": "Tom Baker",
                                                "username": "",
                                                "image": "",
                                                "network_user_id": "7788990011"
                                            },
                                            "latest": {
                                                "text": "Thanks, see you then!",
                                                "at": "2026-10-22 07:10:33"
                                            },
                                            "labels": [],
                                            "assigned_to": null,
                                            "assigned_by": null,
                                            "reviewed_by": null,
                                            "last_activity_at": "2026-10-22 07:10:33"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (account_id missing or not a valid encrypted id.)\n\nstatus must be to_review, assigned or reviewed; type must be comment, message or review. (status or type is not one of the allowed values.)\n\nupdated_since must be a datetime like 2026-10-15T09:30:00+05:30. (updated_since cannot be parsed as a datetime.)\n\nThe inbox covers Facebook pages, LinkedIn company pages, Google Business locations and Instagram business accounts; this account is none of those. (account_id is an account of another network.)\n\nInvalid workspace_id. (workspace_id is not a valid encrypted id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (account_id does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "This social account is not part of the selected workspace. (The account is the owner's but is not in the workspace.)\n\nWorkspace not found or you do not have access to it. (workspace_id names a workspace you are not a member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_item": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "One inbox item in full: a comment or review with its comments, or a conversation with its newest page of messages.",
                "description": "Returns one item in the shape of `/api/inbox_list`, plus its content. A `comment` or `review` item carries `post.media` (every media URL of the post) and `comments` (the comment that raised the item first, then the replies under it, including the account's own). A `message` item carries `total_messages`, `page`, `per_page` and `messages`: the newest page of the conversation, with the messages of that page oldest first.\n\nItem id versus comment id: `item.id` is the item; `item.comments[].id` and `item.messages[].id` are comment ids. Reply, like and AI endpoints take the item id; `/api/inbox_delete_comment` takes a comment id.",
                "operationId": "inbox_item",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Item id (plain integer) from `/api/inbox_list`.",
                                        "example": 58213
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Page of messages, starting at 1 for the newest. Only used for a `message` item.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "per_page": {
                                        "type": "integer",
                                        "description": "Messages per page, 1 to 50. Only used for a `message` item.",
                                        "default": "20",
                                        "example": 20
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 58213
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "item": {
                                            "type": "object",
                                            "description": "The item, with every field documented on `/api/inbox_list`, plus the fields below.",
                                            "properties": {
                                                "post": {
                                                    "type": "object",
                                                    "properties": {
                                                        "media": {
                                                            "type": "array",
                                                            "items": {
                                                                "type": "string",
                                                                "description": "Every media URL of the post, in order. Comment and review items only."
                                                            }
                                                        }
                                                    }
                                                },
                                                "comments": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "array",
                                                        "items": [],
                                                        "description": "Comment and review items only. The comment that raised the item first, then the replies under it. Each entry has the comment shape below.",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "Comment id (plain integer). Use it as `parent_id`, `comment_id` or the `id` of `/api/inbox_delete_comment`."
                                                            },
                                                            "parent_id": {
                                                                "type": "integer",
                                                                "description": "Comment id this one replies to, 0 for a top-level comment."
                                                            },
                                                            "network_comment_id": {
                                                                "type": "string",
                                                                "description": "Id of the comment on the network."
                                                            },
                                                            "text": {
                                                                "type": "string",
                                                                "description": "Comment text."
                                                            },
                                                            "image": {
                                                                "type": "string",
                                                                "description": "Image attached to the comment, or empty."
                                                            },
                                                            "video": {
                                                                "type": "string",
                                                                "description": "Video attached to the comment, or empty."
                                                            },
                                                            "likes": {
                                                                "type": "integer",
                                                                "description": "Like count of the comment."
                                                            },
                                                            "replies": {
                                                                "type": "integer",
                                                                "description": "Reply count of the comment."
                                                            },
                                                            "liked": {
                                                                "type": "boolean",
                                                                "description": "Whether the account has liked this comment."
                                                            },
                                                            "status": {
                                                                "type": "string",
                                                                "description": "`active` or `deleted`. Deleted comments stay in the list."
                                                            },
                                                            "direction": {
                                                                "type": "string",
                                                                "description": "`in` when someone else wrote it, `out` when the account itself did (a reply the account gave)."
                                                            },
                                                            "from": {
                                                                "type": "object",
                                                                "properties": {
                                                                    "name": {
                                                                        "type": "string",
                                                                        "description": "Who wrote it; the account name for `out`."
                                                                    },
                                                                    "image": {
                                                                        "type": "string",
                                                                        "description": "Their profile picture URL, empty for `out`."
                                                                    }
                                                                }
                                                            },
                                                            "created_at": {
                                                                "type": "string",
                                                                "format": "date-time",
                                                                "description": "When it was written."
                                                            }
                                                        }
                                                    }
                                                },
                                                "total_messages": {
                                                    "type": "integer",
                                                    "description": "Message items only. Messages in the whole conversation."
                                                },
                                                "page": {
                                                    "type": "integer",
                                                    "description": "Message items only. Page returned (1 is the newest)."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Message items only. Page size applied."
                                                },
                                                "messages": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "array",
                                                        "items": [],
                                                        "description": "Message items only. The messages of the page, oldest first, each in the comment shape above (`direction` `out` is a message the account sent)."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "item": {
                                        "id": 58213,
                                        "type": "comment",
                                        "status": "to_review",
                                        "bookmarked": false,
                                        "liked": false,
                                        "from": {
                                            "name": "Maria Lopez",
                                            "username": "maria.lopez",
                                            "image": "https://graph.facebook.com/10223/picture",
                                            "network_user_id": "10223344556677"
                                        },
                                        "latest": {
                                            "text": "Do you open on Sundays?",
                                            "at": "2026-10-22 08:42:10"
                                        },
                                        "post": {
                                            "id": "1234567890_987654321",
                                            "type": "image",
                                            "text": "New autumn blends are in.",
                                            "image": "https://scontent.example.com/autumn.jpg",
                                            "video": "",
                                            "link": "",
                                            "title": "",
                                            "permalink": "https://www.facebook.com/1234567890/posts/987654321",
                                            "likes": 41,
                                            "comments": 6,
                                            "posted_at": "2026-10-21 17:00:00",
                                            "media": [
                                                "https://scontent.example.com/autumn.jpg"
                                            ]
                                        },
                                        "labels": [],
                                        "assigned_to": null,
                                        "assigned_by": null,
                                        "reviewed_by": null,
                                        "last_activity_at": "2026-10-22 09:05:44",
                                        "comments": [
                                            {
                                                "id": 90411,
                                                "parent_id": 0,
                                                "network_comment_id": "987654321_111222333",
                                                "text": "Do you open on Sundays?",
                                                "image": "",
                                                "video": "",
                                                "likes": 1,
                                                "replies": 1,
                                                "liked": false,
                                                "status": "active",
                                                "direction": "in",
                                                "from": {
                                                    "name": "Maria Lopez",
                                                    "image": "https://graph.facebook.com/10223/picture"
                                                },
                                                "created_at": "2026-10-22 08:42:10"
                                            },
                                            {
                                                "id": 90415,
                                                "parent_id": 90411,
                                                "network_comment_id": "987654321_111222444",
                                                "text": "Yes, 9am to 4pm.",
                                                "image": "",
                                                "video": "",
                                                "likes": 0,
                                                "replies": 0,
                                                "liked": false,
                                                "status": "active",
                                                "direction": "out",
                                                "from": {
                                                    "name": "Acme Coffee",
                                                    "image": ""
                                                },
                                                "created_at": "2026-10-22 09:05:44"
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id missing or not a positive integer.)\n\nInvalid workspace_id. (workspace_id is not a valid encrypted id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The item's account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Inbox item not found. (No item with that id sits on one of the workspace owner's accounts.)\n\nThis social account is not part of the selected workspace. (The item's account is not in the workspace you named.)\n\nWorkspace not found or you do not have access to it. (workspace_id names a workspace you are not a member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_conversation": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "One page of messages of a conversation item, newest page first.",
                "description": "Returns the messages of a `message` item together with who the conversation is with. Page 1 is the newest page; inside a page the messages are oldest first, so a page renders top to bottom like a chat. `direction` `out` marks a message the account sent. Conversations exist on Facebook pages and Instagram business accounts.",
                "operationId": "inbox_conversation",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Item id (plain integer) of a `message` item.",
                                        "example": 58190
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Page of messages, starting at 1 for the newest.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "per_page": {
                                        "type": "integer",
                                        "description": "Messages per page, 1 to 50.",
                                        "default": "20",
                                        "example": 20
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 58190
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "id": {
                                            "type": "integer",
                                            "description": "The item id."
                                        },
                                        "account": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted account id the conversation belongs to."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Account name."
                                                },
                                                "network": {
                                                    "type": "string",
                                                    "description": "`facebook` or `instagram`."
                                                }
                                            }
                                        },
                                        "with": {
                                            "type": "object",
                                            "properties": {
                                                "name": {
                                                    "type": "string",
                                                    "description": "Display name of the person on the other side."
                                                },
                                                "username": {
                                                    "type": "string",
                                                    "description": "Their handle, when the network gives one."
                                                },
                                                "image": {
                                                    "type": "string",
                                                    "description": "Their profile picture URL, or empty."
                                                },
                                                "network_user_id": {
                                                    "type": "string",
                                                    "description": "Their id on the network."
                                                }
                                            }
                                        },
                                        "total_messages": {
                                            "type": "integer",
                                            "description": "Messages in the whole conversation."
                                        },
                                        "page": {
                                            "type": "integer",
                                            "description": "Page returned."
                                        },
                                        "per_page": {
                                            "type": "integer",
                                            "description": "Page size applied."
                                        },
                                        "messages": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Messages of the page, oldest first, in the comment shape of `/api/inbox_item` (`id`, `parent_id`, `network_comment_id`, `text`, `image`, `video`, `likes`, `replies`, `liked`, `status`, `direction`, `from`, `created_at`)."
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "id": 58190,
                                    "account": {
                                        "id": "aK3mZ8vQr1==",
                                        "name": "Acme Coffee",
                                        "network": "facebook"
                                    },
                                    "with": {
                                        "name": "Tom Baker",
                                        "username": "",
                                        "image": "",
                                        "network_user_id": "7788990011"
                                    },
                                    "total_messages": 2,
                                    "page": 1,
                                    "per_page": 20,
                                    "messages": [
                                        {
                                            "id": 90380,
                                            "parent_id": 0,
                                            "network_comment_id": "m_AbC123",
                                            "text": "Hi, do you deliver?",
                                            "image": "",
                                            "video": "",
                                            "likes": 0,
                                            "replies": 0,
                                            "liked": false,
                                            "status": "active",
                                            "direction": "in",
                                            "from": {
                                                "name": "Tom Baker",
                                                "image": ""
                                            },
                                            "created_at": "2026-10-22 07:02:15"
                                        },
                                        {
                                            "id": 90381,
                                            "parent_id": 0,
                                            "network_comment_id": "m_AbC124",
                                            "text": "We do, within 5 km.",
                                            "image": "",
                                            "video": "",
                                            "likes": 0,
                                            "replies": 0,
                                            "liked": false,
                                            "status": "active",
                                            "direction": "out",
                                            "from": {
                                                "name": "Acme Coffee",
                                                "image": ""
                                            },
                                            "created_at": "2026-10-22 07:10:33"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id missing or not a positive integer.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The item's account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Inbox item not found. (No item with that id sits on one of the workspace owner's accounts.)\n\nThis social account is not part of the selected workspace. (The item's account is not in the workspace you named.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This item is a comment, not a conversation; read it with inbox_item or inbox_comments. (id is a comment item (the word changes to `review` for a review item).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_comments": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "Every comment of a comment or review item: the one that raised it, the replies under it, and the account's own replies.",
                "description": "Returns the comments of a `comment` or `review` item without the rest of the item: top-level comments first (the one that raised the item leads), then replies, each group oldest first. For a Google Business review the list holds the reply the location gave, if any, as an `out` entry. Deleted comments stay in the list with `status` `deleted`.",
                "operationId": "inbox_comments",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Item id (plain integer) of a `comment` or `review` item.",
                                        "example": 58213
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 58213
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "id": {
                                            "type": "integer",
                                            "description": "The item id."
                                        },
                                        "account": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted account id."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Account name."
                                                },
                                                "network": {
                                                    "type": "string",
                                                    "description": "`facebook`, `linkedin`, `google_my_business` or `instagram`."
                                                }
                                            }
                                        },
                                        "post_id": {
                                            "type": "string",
                                            "description": "Id of the post (or Google review) on the network."
                                        },
                                        "post_link": {
                                            "type": "string",
                                            "description": "URL of the post on the network."
                                        },
                                        "comments": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Comments in the comment shape of `/api/inbox_item` (`id`, `parent_id`, `network_comment_id`, `text`, `image`, `video`, `likes`, `replies`, `liked`, `status`, `direction`, `from`, `created_at`)."
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "id": 58213,
                                    "account": {
                                        "id": "aK3mZ8vQr1==",
                                        "name": "Acme Coffee",
                                        "network": "facebook"
                                    },
                                    "post_id": "1234567890_987654321",
                                    "post_link": "https://www.facebook.com/1234567890/posts/987654321",
                                    "comments": [
                                        {
                                            "id": 90411,
                                            "parent_id": 0,
                                            "network_comment_id": "987654321_111222333",
                                            "text": "Do you open on Sundays?",
                                            "image": "",
                                            "video": "",
                                            "likes": 1,
                                            "replies": 1,
                                            "liked": false,
                                            "status": "active",
                                            "direction": "in",
                                            "from": {
                                                "name": "Maria Lopez",
                                                "image": "https://graph.facebook.com/10223/picture"
                                            },
                                            "created_at": "2026-10-22 08:42:10"
                                        },
                                        {
                                            "id": 90415,
                                            "parent_id": 90411,
                                            "network_comment_id": "987654321_111222444",
                                            "text": "Yes, 9am to 4pm.",
                                            "image": "",
                                            "video": "",
                                            "likes": 0,
                                            "replies": 0,
                                            "liked": false,
                                            "status": "active",
                                            "direction": "out",
                                            "from": {
                                                "name": "Acme Coffee",
                                                "image": ""
                                            },
                                            "created_at": "2026-10-22 09:05:44"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id missing or not a positive integer.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The item's account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Inbox item not found. (No item with that id sits on one of the workspace owner's accounts.)\n\nThis social account is not part of the selected workspace. (The item's account is not in the workspace you named.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This item is a conversation; read it with inbox_conversation. (id is a message item.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_team_members": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "Team members who can be assigned items of an account.",
                "description": "Lists the active team members of the workspace owner who have access to the account through a workspace, plus the owner's own seat. The `id` values are the encrypted user ids that `/api/inbox_assign` takes as `user_id` and `/api/inbox_list` takes as `assigned_to`.",
                "operationId": "inbox_team_members",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted account id from `/api/inbox_accounts`.",
                                        "example": "aK3mZ8vQr1=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "account_id"
                                ],
                                "example": {
                                    "account_id": "aK3mZ8vQr1=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "account": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted account id."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Account name."
                                                },
                                                "network": {
                                                    "type": "string",
                                                    "description": "Network key of the account."
                                                }
                                            }
                                        },
                                        "members": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted user id."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "First and last name."
                                                    },
                                                    "image": {
                                                        "type": "string",
                                                        "description": "Profile photo URL, or `null`."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "account": {
                                        "id": "aK3mZ8vQr1==",
                                        "name": "Acme Coffee",
                                        "network": "facebook"
                                    },
                                    "members": [
                                        {
                                            "id": "Jd9kR3tY2w==",
                                            "name": "Jane Doe",
                                            "image": null
                                        },
                                        {
                                            "id": "MRBkPwJx4i8=",
                                            "name": "Sam Patel",
                                            "image": "https://cdn.recurpost.com/u/4821.jpg"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (account_id missing or not a valid encrypted id.)\n\nThe inbox covers Facebook pages, LinkedIn company pages, Google Business locations and Instagram business accounts; this account is none of those. (account_id is an account of another network.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (account_id does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "This social account is not part of the selected workspace. (The account is not in the workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_label_list": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "Labels of one account.",
                "description": "Labels are per account, not per workspace: a label created on one Facebook page is not available on another. Returns the account's labels, newest first. Label ids are plain integers.",
                "operationId": "inbox_label_list",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted account id from `/api/inbox_accounts`.",
                                        "example": "aK3mZ8vQr1=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "account_id"
                                ],
                                "example": {
                                    "account_id": "aK3mZ8vQr1=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "account": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted account id."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Account name."
                                                },
                                                "network": {
                                                    "type": "string",
                                                    "description": "Network key of the account."
                                                }
                                            }
                                        },
                                        "labels": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Label id (plain integer)."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Label name."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "account": {
                                        "id": "aK3mZ8vQr1==",
                                        "name": "Acme Coffee",
                                        "network": "facebook"
                                    },
                                    "labels": [
                                        {
                                            "id": 15,
                                            "name": "Complaint"
                                        },
                                        {
                                            "id": 12,
                                            "name": "Question"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (account_id missing or not a valid encrypted id.)\n\nThe inbox covers Facebook pages, LinkedIn company pages, Google Business locations and Instagram business accounts; this account is none of those. (account_id is an account of another network.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (account_id does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "This social account is not part of the selected workspace. (The account is not in the workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_label_create": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "Adds a label to an account.",
                "description": "Creates a label on one account and returns it. Names are trimmed; the same name twice on one account is refused. RecurPost only, nothing reaches the network.",
                "operationId": "inbox_label_create",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted account id from `/api/inbox_accounts`.",
                                        "example": "aK3mZ8vQr1=="
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "Label name. Leading and trailing spaces are removed.",
                                        "example": "Urgent"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "account_id",
                                    "name"
                                ],
                                "example": {
                                    "account_id": "aK3mZ8vQr1==",
                                    "name": "Urgent"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Label added`."
                                        },
                                        "label": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "New label id (plain integer)."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "The stored name."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Label added",
                                    "label": {
                                        "id": 18,
                                        "name": "Urgent"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (account_id or name missing, or name blank after trimming.)\n\nThe inbox covers Facebook pages, LinkedIn company pages, Google Business locations and Instagram business accounts; this account is none of those. (account_id is an account of another network.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (account_id does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "This social account is not part of the selected workspace. (The account is not in the workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Label already exist. (The account already has a label with that name.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_label_update": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "Renames a label.",
                "description": "Renames one label of one of the workspace owner's accounts. Another label with the new name on the same account is refused. RecurPost only.",
                "operationId": "inbox_label_update",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Label id (plain integer) from `/api/inbox_label_list`.",
                                        "example": 18
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "New name. Leading and trailing spaces are removed.",
                                        "example": "Very urgent"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "id",
                                    "name"
                                ],
                                "example": {
                                    "id": 18,
                                    "name": "Very urgent"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Label updated`."
                                        },
                                        "label": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "Label id."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "The new name."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Label updated",
                                    "label": {
                                        "id": 18,
                                        "name": "Very urgent"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id or name missing, or name blank after trimming.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The label's account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Label not found. (No label with that id sits on one of the workspace owner's accounts.)\n\nThis social account is not part of the selected workspace. (The label's account is not in the workspace you named.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Another label of this account already has that name. (A different label on the same account already uses the new name.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_label_delete": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "Deletes a label and removes it from every item.",
                "description": "Deletes one label of one of the workspace owner's accounts and takes it off every item that carried it. Cannot be undone. RecurPost only.",
                "operationId": "inbox_label_delete",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Label id (plain integer) from `/api/inbox_label_list`.",
                                        "example": 18
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 18
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Label deleted`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Label deleted"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id missing or not a positive integer.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The label's account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Label not found. (No label with that id sits on one of the workspace owner's accounts.)\n\nThis social account is not part of the selected workspace. (The label's account is not in the workspace you named.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_item_labels": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "Puts labels on items of one account, takes them off, or replaces them.",
                "description": "Changes the labels of up to 50 items that all belong to the same account. `add` appends the given labels, `remove` takes them off, `set` replaces every label of the items with the given ones (an empty `label_ids` with `set` clears them). Every label id must exist on that account. Answers the labels each item carries afterwards. RecurPost only.",
                "operationId": "inbox_item_labels",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Item ids (plain integers) as an array or a comma-separated string, at most 50, all on the same account.",
                                        "example": [
                                            58213,
                                            58201
                                        ]
                                    },
                                    "label_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Label ids (plain integers) of that account, as an array or a comma-separated string. Required for `add` and `remove`; may be empty with `set` to clear every label.",
                                        "example": [
                                            12
                                        ]
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "`add` appends, `remove` takes off, `set` replaces.",
                                        "enum": [
                                            "add",
                                            "remove",
                                            "set"
                                        ],
                                        "default": "add",
                                        "example": "add"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "id",
                                    "label_ids"
                                ],
                                "example": {
                                    "id": [
                                        58213,
                                        58201
                                    ],
                                    "label_ids": [
                                        12
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "items": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Item id."
                                                    },
                                                    "labels": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "object",
                                                            "properties": {
                                                                "id": {
                                                                    "type": "integer",
                                                                    "description": "Label id now on the item."
                                                                },
                                                                "name": {
                                                                    "type": "string",
                                                                    "description": "Label name."
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "items": [
                                        {
                                            "id": 58213,
                                            "labels": [
                                                {
                                                    "id": 12,
                                                    "name": "Question"
                                                }
                                            ]
                                        },
                                        {
                                            "id": 58201,
                                            "labels": [
                                                {
                                                    "id": 12,
                                                    "name": "Question"
                                                },
                                                {
                                                    "id": 15,
                                                    "name": "Complaint"
                                                }
                                            ]
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id missing, or label_ids empty with action add or remove.)\n\nAt most 50 ids per call; 60 were sent. (More than 50 item ids.)\n\naction must be add, remove or set. (action is something else.)\n\nAll ids must belong to the same account. (The items span several accounts.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The items' account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Inbox item not found. (Any id is not an item on one of the workspace owner's accounts.)\n\nLabel 999 is not on this account; see inbox_label_list. (A label id is not a label of the items' account; the message lists the offending ids.)\n\nThis social account is not part of the selected workspace. (The items' account is not in the workspace you named.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_reply_comment": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "Replies to a comment or review item on the network.",
                "description": "Posts a reply from the account. By default it goes under the comment that raised the item; `parent_id` names another comment of the same item to reply under instead. For a Google Business review the reply answers the review itself (Google keeps one reply per review, so a second call replaces it). The reply is published on the network through the account's connection and then recorded in the inbox as an `out` comment.\nWhat each network accepts:\n- Facebook page: `text`, `attachment_url` (an image, uploaded to the page and attached to the comment), or both.\n- LinkedIn company page: `text`, `attachment_url` (an image), or both.\n- Instagram business: `text` only; `attachment_url` is ignored.\n- Google Business: `text` only; `attachment_url` is ignored.\n\nThis reaches the network: The reply is published on Facebook, LinkedIn, Instagram or Google under the account's name immediately. There is no draft step.\n\nRead the reply back: After a 200, `/api/inbox_comments` lists the new reply with `direction` `out`. The success body carries no comment id.",
                "operationId": "inbox_reply_comment",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Item id (plain integer) of a `comment` or `review` item.",
                                        "example": 58213
                                    },
                                    "text": {
                                        "type": "string",
                                        "description": "Reply text. Required unless `attachment_url` is sent; at least one of the two must be present.",
                                        "example": "Yes, we open 9am to 4pm on Sundays."
                                    },
                                    "attachment_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public http or https URL of an image to attach. The host must resolve to a public IP address; localhost, private and reserved ranges are refused with 415. Used on Facebook and LinkedIn, ignored on Instagram and Google Business.",
                                        "example": "https://cdn.example.com/opening-hours.jpg"
                                    },
                                    "parent_id": {
                                        "type": "integer",
                                        "description": "Comment id (plain integer, from `/api/inbox_item` or `/api/inbox_comments`) to reply under. Must belong to the same item. Defaults to the comment that raised the item; not used for Google Business reviews.",
                                        "example": 90411
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "id",
                                    "text"
                                ],
                                "example": {
                                    "id": 58213,
                                    "text": "Yes, we open 9am to 4pm on Sundays."
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Reply posted`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Reply posted"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id missing, or both text and attachment_url empty.)\n\nFailed to proceed request, Try again later! (The network rejected the reply.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The item's account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Inbox item not found. (No item with that id sits on one of the workspace owner's accounts.)\n\nparent_id is not a comment of this item. (parent_id is unknown or belongs to another item.)\n\nWe can't find post detail (The inbox no longer holds the post the item points at.)\n\nThis social account is not part of the selected workspace. (The item's account is not in the workspace you named.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This item is a conversation; answer it with inbox_reply_message. (id is a message item.)\n\nThis account needs to be reconnected in RecurPost before its inbox can be used. (The account's token has expired, or the network refused the call for a permission the connection lacks.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "attachment_url must be a publicly reachable http or https URL. (attachment_url is not http(s), has no host, or its host resolves to a private or reserved address.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_reply_message": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "Sends a direct message in a conversation item.",
                "description": "Sends a message from the account to the person of a `message` item: `text`, `attachment_url` (an image), or both (sent as two messages, text first). Works on Facebook pages and Instagram business accounts, the only networks with conversations in the inbox. Each network's messaging window applies: Facebook and Instagram only let a page or account answer within 24 hours of the person's last message, and the network rejects the call outside it.\n\nThis reaches the network: The message is delivered to the person on Facebook Messenger or Instagram immediately.",
                "operationId": "inbox_reply_message",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Item id (plain integer) of a `message` item.",
                                        "example": 58190
                                    },
                                    "text": {
                                        "type": "string",
                                        "description": "Message text. Required unless `attachment_url` is sent; at least one of the two must be present.",
                                        "example": "We deliver within 5 km, order on our site."
                                    },
                                    "attachment_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public http or https URL of an image to send. The host must resolve to a public IP address; localhost, private and reserved ranges are refused with 415.",
                                        "example": "https://cdn.example.com/menu.jpg"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "id",
                                    "text"
                                ],
                                "example": {
                                    "id": 58190,
                                    "text": "We deliver within 5 km, order on our site."
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Reply sent`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Reply sent"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id missing, or both text and attachment_url empty.)\n\n(the network's error text) (Facebook or Instagram refused the message, for example outside the 24-hour window.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The item's account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Inbox item not found. (No item with that id sits on one of the workspace owner's accounts.)\n\nWe can't find post detail (The inbox no longer holds the conversation.)\n\nWe can't find sender detail (The inbox no longer knows the person on the other side.)\n\nThis social account is not part of the selected workspace. (The item's account is not in the workspace you named.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This item is a comment; answer it with inbox_reply_comment. (id is a comment or review item (the word changes accordingly).)\n\nThis account needs to be reconnected in RecurPost before its inbox can be used. (The account's token has expired.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "attachment_url must be a publicly reachable http or https URL. (attachment_url is not http(s), has no host, or its host resolves to a private or reserved address.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_delete_comment": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "Deletes a comment from the network and marks it deleted in the inbox.",
                "description": "Deletes one comment: someone's comment on the account's post, or a reply the account gave. The `id` is a comment id from `/api/inbox_item` or `/api/inbox_comments`, not an item id. The comment is removed on the network and kept in the inbox with `status` `deleted`; the item stays. Supported on Facebook pages, LinkedIn company pages and Instagram business accounts (any comment on the account's post) and on Google Business (the location's own reply to the review). Messages of a conversation cannot be deleted.\n\nThis reaches the network and cannot be undone: The comment is deleted on Facebook, LinkedIn, Instagram or Google. Deleting the comment that raised an item does not remove the item from the inbox.",
                "operationId": "inbox_delete_comment",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Comment id (plain integer). Not an item id.",
                                        "example": 90411
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 90411
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Comment deleted`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Comment deleted"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id missing or not a positive integer.)\n\nFailed to proceed request, Try again later! (The network rejected the delete.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The comment's account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Comment not found in the inbox. (No comment with that id sits on one of the workspace owner's accounts.)\n\nThis social account is not part of the selected workspace. (The comment's account is not in the workspace you named.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This comment is already deleted. (The comment was deleted before.)\n\nThis account needs to be reconnected in RecurPost before its inbox can be used. (The account's token has expired, or LinkedIn refused for a missing permission.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_like": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "Likes or unlikes the post of an item, or one of its comments.",
                "description": "Without `comment_id` the like applies to the post of the item (a `comment` or `review` item); with `comment_id` it applies to that comment of the item. On Facebook pages and LinkedIn company pages the like is sent to the network as the page. On Instagram business and Google Business the app has no like call, so the request is refused with 409 instead of recording a like nobody sees. Message items (conversations) are refused with 400.",
                "operationId": "inbox_like",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Item id (plain integer) of a `comment` or `review` item.",
                                        "example": 58213
                                    },
                                    "comment_id": {
                                        "type": "integer",
                                        "description": "Comment id (plain integer) of the item to like instead of its post. Must belong to the same item.",
                                        "example": 90411
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "`like` or `unlike`.",
                                        "enum": [
                                            "like",
                                            "unlike"
                                        ],
                                        "default": "like",
                                        "example": "like"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 58213
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Liked` or `Unliked`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Liked"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id missing or not a positive integer.)\n\naction must be like or unlike. (action is something else.)\n\nLikes apply to comment and review items, not to messages. (The item is a `message` item.)\n\nFailed to proceed request, Try again later! (Facebook or LinkedIn rejected the like.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The item's account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Inbox item not found. (No item with that id sits on one of the workspace owner's accounts.)\n\ncomment_id is not a comment of this item. (comment_id is unknown or belongs to another item.)\n\nWe can't find post detail (The inbox no longer holds the post the item points at.)\n\nThis social account is not part of the selected workspace. (The item's account is not in the workspace you named.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Likes are not supported on instagram through RecurPost. (The item's account is Instagram or Google Business (the network name in the text varies).)\n\nThis account needs to be reconnected in RecurPost before its inbox can be used. (The account's token has expired, or LinkedIn refused for a missing permission.)\n\nPost is already liked (The post already has the state you asked for; also `Post is already Unliked`, `Comment is already liked`, `Comment is already Unliked`.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_mark_reviewed": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "Marks items as reviewed, or puts them back to to_review.",
                "description": "Moves up to 50 items to status `reviewed` and records you as `reviewed_by`; any assignment on them is cleared. `unreview` moves them back to `to_review`. The items may sit on different accounts of the workspace owner. RecurPost only.\n\nAssignments are cleared: Both `review` and `unreview` remove any team member assignment from the items; `reviewed_by` is set to you either way.",
                "operationId": "inbox_mark_reviewed",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Item ids (plain integers) as an array or a comma-separated string, at most 50.",
                                        "example": [
                                            58213,
                                            58190
                                        ]
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "`review` marks reviewed, `unreview` returns the items to `to_review`.",
                                        "enum": [
                                            "review",
                                            "unreview"
                                        ],
                                        "default": "review",
                                        "example": "review"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": [
                                        58213,
                                        58190
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "reviewed_count": {
                                            "type": "integer",
                                            "description": "Number of items changed (for both actions)."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "reviewed_count": 2
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id missing or holds no positive integer.)\n\nAt most 50 ids per call; 60 were sent. (More than 50 ids.)\n\naction must be review or unreview. (action is something else.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (An item's account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Inbox item not found. (Any id is not an item on one of the workspace owner's accounts.)\n\nThis social account is not part of the selected workspace. (An item's account is not in the workspace you named.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_bookmark": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "Bookmarks items or removes the bookmark.",
                "description": "Sets or clears the bookmark on up to 50 items of the workspace owner's accounts in one write. Bookmarks are a RecurPost flag; filter on them with `bookmarked=true` in `/api/inbox_list`.",
                "operationId": "inbox_bookmark",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Item ids (plain integers) as an array or a comma-separated string, at most 50.",
                                        "example": [
                                            58213
                                        ]
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "`add` bookmarks, `remove` clears the bookmark.",
                                        "enum": [
                                            "add",
                                            "remove"
                                        ],
                                        "default": "add",
                                        "example": "add"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": [
                                        58213
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Bookmarked` or `Bookmark removed`."
                                        },
                                        "count": {
                                            "type": "integer",
                                            "description": "Number of items written."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Bookmarked",
                                    "count": 1
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id missing or holds no positive integer.)\n\nAt most 50 ids per call; 60 were sent. (More than 50 ids.)\n\naction must be add or remove. (action is something else.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (An item's account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Inbox item not found. (Any id is not an item on one of the workspace owner's accounts.)\n\nThis social account is not part of the selected workspace. (An item's account is not in the workspace you named.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_assign": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "Assigns items of one account to a team member, or unassigns them.",
                "description": "Hands up to 50 items of the same account to one team member: the items move to status `assigned`, `assigned_to` and `assigned_by` are set, and the member receives an email about the assignment. `unassign` clears the assignment and returns the items to `to_review`. The member must appear in `/api/inbox_team_members` for that account. RecurPost only.\n\nSide effect: Assigning sends the member an assignment notification email. An item can hold one assignment at a time; assigning again replaces it.",
                "operationId": "inbox_assign",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Item ids (plain integers) as an array or a comma-separated string, at most 50, all on the same account.",
                                        "example": [
                                            58213,
                                            58201
                                        ]
                                    },
                                    "user_id": {
                                        "type": "string",
                                        "description": "Encrypted user id from `/api/inbox_team_members`. Required when action is `assign`; ignored for `unassign`.",
                                        "example": "MRBkPwJx4i8="
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "`assign` or `unassign`.",
                                        "enum": [
                                            "assign",
                                            "unassign"
                                        ],
                                        "default": "assign",
                                        "example": "assign"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "id",
                                    "user_id"
                                ],
                                "example": {
                                    "id": [
                                        58213,
                                        58201
                                    ],
                                    "user_id": "MRBkPwJx4i8="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Assigned` or `Unassigned`."
                                        },
                                        "count": {
                                            "type": "integer",
                                            "description": "Number of items changed."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Assigned",
                                    "count": 2
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id missing, or user_id missing with action assign.)\n\nAt most 50 ids per call; 60 were sent. (More than 50 ids.)\n\naction must be assign or unassign. (action is something else.)\n\nAll ids must belong to the same account. (The items span several accounts.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "user_id is not a team member with access to this account; see inbox_team_members. (user_id is not in the account's team member list.)\n\nSorry, there was an issue. Please try again later or contact support. (The items' account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Inbox item not found. (Any id is not an item on one of the workspace owner's accounts.)\n\nThis social account is not part of the selected workspace. (The items' account is not in the workspace you named.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_ai_reply": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "A suggested reply for an item, written by AI; nothing is sent.",
                "description": "Asks RecurPost's AI for a reply suggestion and returns the text. For a `message` item the last 20 stored messages of the conversation are used (empty ones skipped). For a `comment` or `review` item the post text, its link and the comment that raised the item are used; `comment_id` picks another comment of the item to answer instead. The suggestion is only returned; send it yourself with `/api/inbox_reply_comment` or `/api/inbox_reply_message`. No AI credit of the account is consumed.\n\nWorks on any account status: The suggestion is built from stored data, so it is available even when the account needs reconnection.",
                "operationId": "inbox_ai_reply",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Item id (plain integer).",
                                        "example": 58213
                                    },
                                    "comment_id": {
                                        "type": "integer",
                                        "description": "Comment id (plain integer) of the item to answer. Only for comment and review items; defaults to the comment that raised the item.",
                                        "example": 90411
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 58213
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "id": {
                                            "type": "integer",
                                            "description": "The item id."
                                        },
                                        "suggestion": {
                                            "type": "string",
                                            "description": "The suggested reply text."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "id": 58213,
                                    "suggestion": "Hi Maria, yes we do! We are open every Sunday from 9am to 4pm. Hope to see you soon."
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id missing or not a positive integer.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The item's account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Inbox item not found. (No item with that id sits on one of the workspace owner's accounts.)\n\ncomment_id is not a comment of this item. (comment_id is unknown or belongs to another item.)\n\nThis social account is not part of the selected workspace. (The item's account is not in the workspace you named.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This conversation has no text to answer yet. (A message item whose stored messages are all empty (attachments only).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The AI service did not answer.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_sync": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "Refreshes an account's inbox from its network, once per 10 minutes per account.",
                "description": "For a Google Business location this pulls the latest reviews from Google into the inbox. For Facebook pages, LinkedIn company pages and Instagram business accounts the inbox is fed by webhooks; the sync renews the account's webhook subscription so new comments and messages keep arriving. Allowed once every 10 minutes per account; an earlier call answers 429 with a `Retry-After` header. Success is judged by the account's sync time moving.\n\nYou rarely need this: Facebook, LinkedIn and Instagram items arrive through webhooks within seconds without a sync. Call it when items stop arriving for an account, or to pull new Google reviews on demand.",
                "operationId": "inbox_sync",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted account id from `/api/inbox_accounts`.",
                                        "example": "gB9xT4nWp2=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "default": "your default workspace",
                                        "example": "wS7pQ2kLm9=="
                                    }
                                },
                                "required": [
                                    "account_id"
                                ],
                                "example": {
                                    "account_id": "gB9xT4nWp2=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Synced`."
                                        },
                                        "account": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted account id."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Account name."
                                                },
                                                "network": {
                                                    "type": "string",
                                                    "description": "Network key of the account."
                                                }
                                            }
                                        },
                                        "last_synced_at": {
                                            "type": "string",
                                            "format": "date-time",
                                            "description": "The new sync time, in the workspace owner's timezone."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Synced",
                                    "account": {
                                        "id": "gB9xT4nWp2==",
                                        "name": "Acme Coffee - Downtown",
                                        "network": "google_my_business"
                                    },
                                    "last_synced_at": "2026-10-22 10:02:41"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (account_id missing or not a valid encrypted id.)\n\nThe inbox covers Facebook pages, LinkedIn company pages, Google Business locations and Instagram business accounts; this account is none of those. (account_id is an account of another network.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (account_id does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "This social account is not part of the selected workspace. (The account is not in the workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This account needs to be reconnected in RecurPost before its inbox can be used. (The account's token has expired, or the network refused the subscription renewal.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "This account was synced less than 10 minutes ago. Try again in 412 seconds. (Less than 10 minutes since the last sync; `Retry-After` carries the same number of seconds.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "502": {
                        "description": "The account could not be synced; its connection may need attention in RecurPost. (The network call went through but the sync time did not move (typically Google refused the pull).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_ai_review_summary": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "AI-written summary or testimonial text from a review item.",
                "description": "Turns review item `item_id` (a `/api/inbox_list` item of type review, from a Facebook page or Google Business location) into a short piece of copy: a summary or testimonial built from the review text, the reviewer's name and the rating. Nothing is posted or sent and no AI credit is spent; use the text in a post or a testimonial template as you see fit.",
                "operationId": "inbox_ai_review_summary",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "item_id": {
                                        "type": "integer",
                                        "description": "Plain integer id of a review item from `/api/inbox_list`.",
                                        "example": 73105
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "item_id"
                                ],
                                "example": {
                                    "item_id": 73105
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`"
                                        },
                                        "item_id": {
                                            "type": "integer",
                                            "description": "The review item."
                                        },
                                        "text": {
                                            "type": "string",
                                            "description": "The AI copy."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "item_id": 73105,
                                    "text": "Jane called the service quick and friendly and gave us five stars."
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nitem_id must be a review item. (The item is a post, comment or message.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The item's account belongs to another user.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nInbox item not found. (No item with that id belongs to an account of the workspace owner.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the item's account sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The AI did not answer; the app's own message and status replace these when it sent them.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/inbox_to_library": {
            "post": {
                "tags": [
                    "Inbox"
                ],
                "summary": "Copy an inbox item or a comment into one or more libraries.",
                "description": "Saves the text and media of an inbox item (`item_id`: a post, review or message item from `/api/inbox_list`) or of one comment (`comment_id` from `/api/inbox_comments`) as a new post in every library in `library_ids`. Send either `item_id` or `comment_id`; when both are sent the comment wins. Each copy counts toward the plan's library post limit.",
                "operationId": "inbox_to_library",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "library_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted library ids: one id, a comma-separated string, a JSON array string or an array. All ids must decrypt or the list is treated as empty.",
                                        "example": [
                                            "nX2k9Qp7Lw=="
                                        ]
                                    },
                                    "item_id": {
                                        "type": "integer",
                                        "description": "Plain integer id of an inbox item (post, review or message). Required unless comment_id is sent.",
                                        "example": 73105
                                    },
                                    "comment_id": {
                                        "type": "integer",
                                        "description": "Plain integer id of a comment from `/api/inbox_comments`. Takes precedence over item_id.",
                                        "example": 88021
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7pQ2mN1x=="
                                    }
                                },
                                "required": [
                                    "library_ids"
                                ],
                                "example": {
                                    "library_ids": [
                                        "nX2k9Qp7Lw=="
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Saved to N library.` or `Saved to N libraries.`"
                                        },
                                        "library_ids": {
                                            "type": "array",
                                            "items": [],
                                            "description": "Encrypted ids of the libraries the content was saved into."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Saved to 1 library.",
                                    "library_ids": [
                                        "nX2k9Qp7Lw=="
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to an id.)\n\nlibrary_ids must hold at least one id. (library_ids is missing or one of its ids does not decrypt.)\n\nContent you are trying to add is currently unavailable or invalid. Please try again later. (The item's content could not be read.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The item's account or a library belongs to another user.)\n\nYou have maximum allowed number of posts in your library. Please upgrade your plan or delete few posts to add new ones. (The copies would pass the owner's library post limit (the upgrade wording varies by plan).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id is not a workspace you own or are an active member of.)\n\nComment not found. (comment_id is not a comment on an account of the workspace owner.)\n\nInbox item not found. (No comment_id was sent and item_id is not an item of the workspace owner.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the item's account sits in another workspace.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and a library sits in another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The app did not answer; its own message replaces this one when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/dm_automation_accounts": {
            "post": {
                "tags": [
                    "DM Automations"
                ],
                "summary": "List the Instagram business accounts that can run comment-to-DM automations.",
                "description": "Returns the connected Instagram business accounts of the workspace, each with the number of automations already set up on it. Only Instagram business accounts can run automations, so other networks are never listed. Use the returned `id` as `account_id` on the other DM Automation endpoints.\n\nNo accounts is not an error: A workspace without Instagram business accounts answers 200 with an empty `accounts` list.",
                "operationId": "dm_automation_accounts",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "accounts": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Instagram business accounts of the workspace. Empty when none is connected.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Encrypted account id. Pass it as `account_id`."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Account name as shown in RecurPost."
                                                    },
                                                    "network": {
                                                        "type": "string",
                                                        "description": "Always `instagram`."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "`active`, `paused` or `needs_reconnection` (the token expired)."
                                                    },
                                                    "automation_count": {
                                                        "type": "integer",
                                                        "description": "Number of automations on the account."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "accounts": [
                                        {
                                            "id": "aB3cD4eF5g==",
                                            "name": "acme.shop",
                                            "network": "instagram",
                                            "status": "active",
                                            "automation_count": 2
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to a workspace id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The account lookup failed inside the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/dm_automation_posts": {
            "post": {
                "tags": [
                    "DM Automations"
                ],
                "summary": "Recent posts and Reels of an Instagram account, to pick the one an automation watches.",
                "description": "Fetches the latest media of the account live from Instagram (up to 12 items) so you can choose the `post_id` an automation should watch. Pass the returned `id` as `post_id` on `/api/dm_automation_create`.\n\nLive Instagram call: Every call hits the Instagram Graph API with the account's token. An expired token (account status `needs_reconnection`) returns an empty list rather than an error; reconnect the account in RecurPost first.",
                "operationId": "dm_automation_posts",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted Instagram account id from `/api/dm_automation_accounts`.",
                                        "example": "aB3cD4eF5g=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "account_id"
                                ],
                                "example": {
                                    "account_id": "aB3cD4eF5g=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "posts": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Latest media of the account, newest first as Instagram returns them.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Instagram media id. This is the `post_id` an automation watches."
                                                    },
                                                    "caption": {
                                                        "type": "string",
                                                        "description": "Caption text, blank when the post has none."
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "description": "Instagram media type in lower case: `image`, `video`, `carousel_album` or `reels`."
                                                    },
                                                    "permalink": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Public URL of the post on Instagram."
                                                    },
                                                    "thumbnail": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Thumbnail URL; the media URL itself when Instagram sends no thumbnail."
                                                    },
                                                    "posted_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When the post went live, in UTC."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "posts": [
                                        {
                                            "id": "17895695668004550",
                                            "caption": "New drop this Friday. Comment PRICE for the link.",
                                            "type": "reels",
                                            "permalink": "https://www.instagram.com/reel/Cx1AbCdEfGh/",
                                            "thumbnail": "https://scontent.cdninstagram.com/v/t51.29350-15/thumb.jpg",
                                            "posted_at": "2026-10-01 10:00:00"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (account_id is missing or does not decrypt to one account id.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nNo social accounts found. (The account row no longer exists in the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nThis social account is not part of the selected workspace. (workspace_id was given and the account is connected to another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The Instagram call failed inside the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/dm_automation_list": {
            "post": {
                "tags": [
                    "DM Automations"
                ],
                "summary": "List the automations of one Instagram account with the DMs each sent in the last 30 days.",
                "description": "Returns every automation on the account in the automation shape described under `/api/dm_automation`, plus `dms_sent_30d`, the number of direct messages the automation sent in the last 30 days.",
                "operationId": "dm_automation_list",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted Instagram account id from `/api/dm_automation_accounts`.",
                                        "example": "aB3cD4eF5g=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "account_id"
                                ],
                                "example": {
                                    "account_id": "aB3cD4eF5g=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "automations": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Automations of the account, each in the automation shape of `/api/dm_automation` (`id`, `account_id`, `name`, `status`, `trigger`, `mode`, `dm`, `comment_replies`, `non_follower_comment_reply`, `follow_loop`, `created_at`).",
                                                "properties": {
                                                    "dms_sent_30d": {
                                                        "type": "integer",
                                                        "description": "Direct messages the automation sent in the last 30 days. Only this endpoint adds the field."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "automations": [
                                        {
                                            "id": 91,
                                            "account_id": "aB3cD4eF5g==",
                                            "name": "Friday drop",
                                            "status": "active",
                                            "trigger": {
                                                "all_posts": false,
                                                "post_id": "17895695668004550",
                                                "post_type": "reels",
                                                "post_media": "https://cdn.recurpost.com/media/12/thumb.jpg",
                                                "all_comments": false,
                                                "keywords": [
                                                    "price",
                                                    "link"
                                                ]
                                            },
                                            "mode": "anyone",
                                            "dm": {
                                                "message": "Here is the link you asked for!",
                                                "button_title": "Shop now",
                                                "button_url": "https://example.com/drop"
                                            },
                                            "comment_replies": [
                                                "Sent you a DM!",
                                                "Check your inbox"
                                            ],
                                            "non_follower_comment_reply": "",
                                            "follow_loop": {
                                                "consent_dm_message": "",
                                                "consent_button_title": "",
                                                "opening_dm_message": "",
                                                "cta_button_title": "",
                                                "unfollower_dm_message": ""
                                            },
                                            "created_at": "2026-10-01 10:00:00",
                                            "dms_sent_30d": 7
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (account_id is missing or does not decrypt to one account id.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nNo social accounts found. (The account row no longer exists in the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nThis social account is not part of the selected workspace. (workspace_id was given and the account is connected to another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The list failed inside the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/dm_automation": {
            "post": {
                "tags": [
                    "DM Automations"
                ],
                "summary": "Read one automation.",
                "description": "Returns one automation by its numeric id. The automation must sit on an Instagram account of the workspace owner.\nThis is the automation shape that `/api/dm_automation_list` also uses. The words the API uses for `status` are `active` (running), `paused` (switched off) and `pending` (set by the app while an automation waits on Instagram; it cannot be set through the API). `mode` is `anyone` or `follow_to_unlock`.",
                "operationId": "dm_automation",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Plain numeric automation id from `/api/dm_automation_list` or `/api/dm_automation_create`.",
                                        "example": 91
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 91
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "automation": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "Numeric automation id."
                                                },
                                                "account_id": {
                                                    "type": "string",
                                                    "description": "Encrypted id of the Instagram account the automation runs on."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Name of the automation; `Untitled` when none was given."
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "`active`, `paused` or `pending`."
                                                },
                                                "trigger": {
                                                    "type": "object",
                                                    "properties": {
                                                        "all_posts": {
                                                            "type": "boolean",
                                                            "description": "true when the automation watches every post of the account."
                                                        },
                                                        "post_id": {
                                                            "type": "string",
                                                            "description": "Instagram media id watched when `all_posts` is false; blank otherwise."
                                                        },
                                                        "post_type": {
                                                            "type": "string",
                                                            "description": "Media type of the watched post as stored (for example `reels`), blank when not recorded."
                                                        },
                                                        "post_media": {
                                                            "type": "string",
                                                            "format": "uri",
                                                            "description": "Thumbnail of the watched post, re-hosted by RecurPost; blank when none."
                                                        },
                                                        "all_comments": {
                                                            "type": "boolean",
                                                            "description": "true when any comment triggers the automation."
                                                        },
                                                        "keywords": {
                                                            "type": "array",
                                                            "items": [],
                                                            "description": "Keywords a comment must contain when `all_comments` is false. Empty otherwise."
                                                        }
                                                    }
                                                },
                                                "mode": {
                                                    "type": "string",
                                                    "description": "`anyone` or `follow_to_unlock`."
                                                },
                                                "dm": {
                                                    "type": "object",
                                                    "properties": {
                                                        "message": {
                                                            "type": "string",
                                                            "description": "Text of the direct message."
                                                        },
                                                        "button_title": {
                                                            "type": "string",
                                                            "description": "Label of the button under the DM; blank when there is no button."
                                                        },
                                                        "button_url": {
                                                            "type": "string",
                                                            "format": "uri",
                                                            "description": "Link the button opens; blank when there is no button."
                                                        }
                                                    }
                                                },
                                                "comment_replies": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "array",
                                                        "items": [],
                                                        "description": "One to three public replies; RecurPost rotates through them when answering comments."
                                                    }
                                                },
                                                "non_follower_comment_reply": {
                                                    "type": "string",
                                                    "description": "Public reply used for non-followers in `follow_to_unlock` mode; blank when unused."
                                                },
                                                "follow_loop": {
                                                    "type": "object",
                                                    "properties": {
                                                        "consent_dm_message": {
                                                            "type": "string",
                                                            "description": "First DM sent to a non-follower in `follow_to_unlock` mode, asking them to follow."
                                                        },
                                                        "consent_button_title": {
                                                            "type": "string",
                                                            "description": "Button label under the consent DM."
                                                        },
                                                        "opening_dm_message": {
                                                            "type": "string",
                                                            "description": "DM sent once the follow check starts."
                                                        },
                                                        "cta_button_title": {
                                                            "type": "string",
                                                            "description": "Button label the user presses after following."
                                                        },
                                                        "unfollower_dm_message": {
                                                            "type": "string",
                                                            "description": "DM sent when the user still does not follow; blank when unused."
                                                        }
                                                    }
                                                },
                                                "created_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "description": "When the automation was created, in UTC."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "automation": {
                                        "id": 92,
                                        "account_id": "aB3cD4eF5g==",
                                        "name": "Follow to unlock guide",
                                        "status": "active",
                                        "trigger": {
                                            "all_posts": true,
                                            "post_id": "",
                                            "post_type": "",
                                            "post_media": "",
                                            "all_comments": true,
                                            "keywords": []
                                        },
                                        "mode": "follow_to_unlock",
                                        "dm": {
                                            "message": "Thanks for following! Here is your guide.",
                                            "button_title": "Download",
                                            "button_url": "https://example.com/guide"
                                        },
                                        "comment_replies": [
                                            "Check your DMs!"
                                        ],
                                        "non_follower_comment_reply": "Follow us and check your DMs!",
                                        "follow_loop": {
                                            "consent_dm_message": "Follow us first and tap the button below.",
                                            "consent_button_title": "I follow you",
                                            "opening_dm_message": "Welcome! Tap below once you follow.",
                                            "cta_button_title": "Send my guide",
                                            "unfollower_dm_message": "Looks like you are not following yet. Follow and tap again."
                                        },
                                        "created_at": "2026-10-03 08:15:00"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or not a positive integer.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The automation's account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nAutomation not found. (No automation has this id.)\n\nThis social account is not part of the selected workspace. (workspace_id was given and the automation's account is connected to another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The read failed inside the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/dm_automation_stats": {
            "post": {
                "tags": [
                    "DM Automations"
                ],
                "summary": "Daily counters of your automations over a date window, by day, automation or account.",
                "description": "Sums the automation counters over a date window. By default the last 30 days (today and the 29 days before it, UTC dates) grouped by day; the window is at most 90 days because the counters are kept 90 days. `group_by` `automation` or `account` gives one row per automation or per account instead. `account_id` and `automation_id` narrow the rows.\nFourteen counters are returned per row and in `totals`: `dm_sent`, `comment_reply_sent`, `non_follower_reply_sent`, `consent_dm_sent`, `consent_follower_dm_sent`, `consent_non_follower_dm_sent`, `consent_expired`, `follower_detected`, `non_follower_detected`, `consent_error`, `opening_dm_sent`, `cta_response_received`, `unfollower_dm_sent` and `cta_loop_completed`. The consent, follower, opening, cta and unfollower counters only move for `follow_to_unlock` automations.\n\nWindow arithmetic: The limit is on the span: `to_date` minus `from_date` must be less than 90 days, so a window of 90 calendar days inclusive (for example 2026-07-04 to 2026-10-01) is the largest accepted.\n\nDeleted automations keep their history: Counters of a deleted automation still appear in `day` and `account` totals and as an `automation` row with a blank name until the 90-day retention drops them.",
                "operationId": "dm_automation_stats",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "from_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "First day of the window, `YYYY-MM-DD`. Defaults to 29 days before `to_date`.",
                                        "default": "to_date minus 29 days",
                                        "example": "2026-10-01"
                                    },
                                    "to_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Last day of the window, `YYYY-MM-DD`. Defaults to today (UTC). Must not be before `from_date`; the window spans at most 90 days.",
                                        "default": "today (UTC)",
                                        "example": "2026-10-21"
                                    },
                                    "group_by": {
                                        "type": "string",
                                        "description": "`day` gives one row per calendar day, newest first. `automation` gives one row per automation, `account` one per account, both in ascending id order.",
                                        "enum": [
                                            "day",
                                            "automation",
                                            "account"
                                        ],
                                        "default": "day",
                                        "example": "day"
                                    },
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted account id; only rows of this account are summed.",
                                        "example": "aB3cD4eF5g=="
                                    },
                                    "automation_id": {
                                        "type": "integer",
                                        "description": "Plain numeric automation id; only rows of this automation are summed. When `account_id` is also given the automation must be on that account.",
                                        "example": 91
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`. When given, only accounts connected to that workspace are summed; without it every workspace of the owner counts.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "from_date": {
                                            "type": "string",
                                            "format": "date",
                                            "description": "First day of the window used."
                                        },
                                        "to_date": {
                                            "type": "string",
                                            "format": "date",
                                            "description": "Last day of the window used."
                                        },
                                        "group_by": {
                                            "type": "string",
                                            "description": "Grouping used: `day`, `automation` or `account`."
                                        },
                                        "rows": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "One row per group. Days without activity are left out.",
                                                "properties": {
                                                    "date": {
                                                        "type": "string",
                                                        "format": "date",
                                                        "description": "The day, only when `group_by` is `day`."
                                                    },
                                                    "automation": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "Automation id, only when `group_by` is `automation`."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Automation name; blank when the automation was deleted since."
                                                            },
                                                            "account_id": {
                                                                "type": "string",
                                                                "description": "Encrypted id of the automation's account."
                                                            }
                                                        }
                                                    },
                                                    "account": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "description": "Encrypted account id, only when `group_by` is `account`."
                                                            },
                                                            "name": {
                                                                "type": "string",
                                                                "description": "Account name."
                                                            },
                                                            "network": {
                                                                "type": "string",
                                                                "description": "Always `instagram`."
                                                            }
                                                        }
                                                    },
                                                    "dm_sent": {
                                                        "type": "integer",
                                                        "description": "Direct messages sent. The thirteen other counters listed in the description follow in the same way, one integer field each."
                                                    }
                                                }
                                            }
                                        },
                                        "totals": {
                                            "type": "object",
                                            "description": "The fourteen counters summed over every row."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "from_date": "2026-10-01",
                                    "to_date": "2026-10-05",
                                    "group_by": "day",
                                    "rows": [
                                        {
                                            "date": "2026-10-02",
                                            "dm_sent": 3,
                                            "comment_reply_sent": 1,
                                            "non_follower_reply_sent": 0,
                                            "consent_dm_sent": 0,
                                            "consent_follower_dm_sent": 0,
                                            "consent_non_follower_dm_sent": 0,
                                            "consent_expired": 0,
                                            "follower_detected": 0,
                                            "non_follower_detected": 0,
                                            "consent_error": 0,
                                            "opening_dm_sent": 0,
                                            "cta_response_received": 0,
                                            "unfollower_dm_sent": 0,
                                            "cta_loop_completed": 0
                                        },
                                        {
                                            "date": "2026-10-01",
                                            "dm_sent": 5,
                                            "comment_reply_sent": 2,
                                            "non_follower_reply_sent": 0,
                                            "consent_dm_sent": 0,
                                            "consent_follower_dm_sent": 0,
                                            "consent_non_follower_dm_sent": 0,
                                            "consent_expired": 0,
                                            "follower_detected": 0,
                                            "non_follower_detected": 0,
                                            "consent_error": 0,
                                            "opening_dm_sent": 0,
                                            "cta_response_received": 0,
                                            "unfollower_dm_sent": 0,
                                            "cta_loop_completed": 0
                                        }
                                    ],
                                    "totals": {
                                        "dm_sent": 8,
                                        "comment_reply_sent": 3,
                                        "non_follower_reply_sent": 0,
                                        "consent_dm_sent": 0,
                                        "consent_follower_dm_sent": 0,
                                        "consent_non_follower_dm_sent": 0,
                                        "consent_expired": 0,
                                        "follower_detected": 0,
                                        "non_follower_detected": 0,
                                        "consent_error": 0,
                                        "opening_dm_sent": 0,
                                        "cta_response_received": 0,
                                        "unfollower_dm_sent": 0,
                                        "cta_loop_completed": 0
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "from_date and to_date must be dates like 2026-10-01. (A date is not a real YYYY-MM-DD date.)\n\nto_date must not be before from_date, and the window is at most 90 days. (The window is reversed or spans 90 days or more.)\n\ngroup_by must be day, automation or account. (group_by is another word.)\n\naccount_id is not a valid account id. (account_id was sent but does not decrypt to one account id.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nThat automation is not on the given account. (Both filters were sent and the automation sits on another account.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (account_id, or the automation's account, does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nThis social account is not part of the selected workspace. (workspace_id was given and the account is connected to another workspace.)\n\nAutomation not found. (automation_id names no automation.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/dm_automation_create": {
            "post": {
                "tags": [
                    "DM Automations"
                ],
                "summary": "Create a comment-to-DM automation on an Instagram business account.",
                "description": "Creates an automation on the account. Choose what it watches (`all_posts` or one `post_id`), what triggers it (`all_comments` or a list of `keywords`), the direct message with its optional button, and one to three public comment replies. In `follow_to_unlock` mode the four follow-loop texts are required as well.\nFields are validated in the order listed under errors before anything is checked against the account, so a bad body answers 400 even on an account you do not own.\n\nSide effects: Creating an automation subscribes the account to Instagram comment webhooks and, when `post_media` is sent, downloads the file onto RecurPost storage. Keywords are trimmed, blank entries dropped, and stored comma-separated; matching is done by the app when comments arrive.\n\nLists in form bodies: `keywords` and `comment_replies` accept a JSON array when the body is JSON. In a form-encoded body send either a JSON-encoded array string such as `[\"price\",\"link\"]` or, for keywords, a comma-separated string.",
                "operationId": "dm_automation_create",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted Instagram business account id from `/api/dm_automation_accounts`. Accounts of other networks are refused.",
                                        "example": "aB3cD4eF5g=="
                                    },
                                    "dm_message": {
                                        "type": "string",
                                        "description": "Text of the direct message sent to the commenter.",
                                        "example": "Here is the link you asked for!"
                                    },
                                    "comment_replies": {
                                        "type": "array",
                                        "items": [],
                                        "description": "One to three public replies posted under the comment; RecurPost rotates through them. Send a JSON array, a single string, or a JSON-encoded array string.",
                                        "example": [
                                            "Sent you a DM!",
                                            "Check your inbox"
                                        ]
                                    },
                                    "all_posts": {
                                        "type": "boolean",
                                        "description": "true to watch every post of the account. Required (as true) when `post_id` is not sent. Accepts true/false, 1/0, yes/no.",
                                        "default": "false",
                                        "example": false
                                    },
                                    "post_id": {
                                        "type": "string",
                                        "description": "Instagram media id from `/api/dm_automation_posts`. Required when `all_posts` is not true; ignored when it is.",
                                        "example": "17895695668004550"
                                    },
                                    "post_type": {
                                        "type": "string",
                                        "description": "Media type of the watched post as returned by `/api/dm_automation_posts` (`type`). Stored for display only.",
                                        "example": "reels"
                                    },
                                    "post_media": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Thumbnail of the watched post, a publicly reachable http or https URL. RecurPost downloads and re-hosts it.",
                                        "example": "https://scontent.cdninstagram.com/v/t51.29350-15/thumb.jpg"
                                    },
                                    "all_comments": {
                                        "type": "boolean",
                                        "description": "true to trigger on any comment. Required (as true) when `keywords` is not sent. When true, `keywords` is dropped.",
                                        "default": "false",
                                        "example": false
                                    },
                                    "keywords": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Words a comment must contain. A JSON array, a JSON-encoded array string, or a comma-separated string. Required when `all_comments` is not true.",
                                        "example": [
                                            "price",
                                            "link"
                                        ]
                                    },
                                    "mode": {
                                        "type": "string",
                                        "description": "`anyone` DMs every commenter. `follow_to_unlock` asks non-followers to follow first and needs `consent_dm_message`, `consent_button_title`, `opening_dm_message` and `cta_button_title`. Case-insensitive.",
                                        "enum": [
                                            "anyone",
                                            "follow_to_unlock"
                                        ],
                                        "default": "anyone",
                                        "example": "anyone"
                                    },
                                    "button_title": {
                                        "type": "string",
                                        "description": "Label of the button under the DM. Send together with `button_url` or not at all.",
                                        "example": "Shop now"
                                    },
                                    "button_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Link the button opens; a publicly reachable http or https URL (no private or local addresses). Send together with `button_title`.",
                                        "example": "https://example.com/drop"
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "Name shown in RecurPost.",
                                        "default": "Untitled",
                                        "example": "Friday drop"
                                    },
                                    "non_follower_comment_reply": {
                                        "type": "string",
                                        "description": "Public reply used for non-followers in `follow_to_unlock` mode.",
                                        "example": "Follow us and check your DMs!"
                                    },
                                    "consent_dm_message": {
                                        "type": "string",
                                        "description": "First DM to a non-follower asking them to follow. Required in `follow_to_unlock` mode.",
                                        "example": "Follow us first and tap the button below."
                                    },
                                    "consent_button_title": {
                                        "type": "string",
                                        "description": "Button label under the consent DM. Required in `follow_to_unlock` mode.",
                                        "example": "I follow you"
                                    },
                                    "opening_dm_message": {
                                        "type": "string",
                                        "description": "DM sent when the follow check starts. Required in `follow_to_unlock` mode.",
                                        "example": "Welcome! Tap below once you follow."
                                    },
                                    "cta_button_title": {
                                        "type": "string",
                                        "description": "Button the user presses after following. Required in `follow_to_unlock` mode.",
                                        "example": "Send my guide"
                                    },
                                    "unfollower_dm_message": {
                                        "type": "string",
                                        "description": "DM sent when the user still does not follow after pressing the button.",
                                        "example": "Looks like you are not following yet. Follow and tap again."
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "account_id",
                                    "dm_message",
                                    "comment_replies"
                                ],
                                "example": {
                                    "account_id": "aB3cD4eF5g==",
                                    "dm_message": "Here is the link you asked for!",
                                    "comment_replies": [
                                        "Sent you a DM!",
                                        "Check your inbox"
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Automation created`."
                                        },
                                        "id": {
                                            "type": "integer",
                                            "description": "Numeric id of the new automation. Use it as `id` on the other endpoints."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Automation created",
                                    "id": 91
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (account_id is missing or does not decrypt to one account id.)\n\nSend all_posts as true, or post_id from dm_automation_posts. (Neither all_posts true nor a post_id was sent.)\n\nSend all_comments as true, or keywords (a list or comma-separated). (Neither all_comments true nor keywords were sent.)\n\nmode must be anyone or follow_to_unlock. (mode is another word.)\n\ndm_message is required. (dm_message is missing or blank.)\n\nbutton_title and button_url go together. (Only one of the two button fields was sent.)\n\nbutton_url must be a publicly reachable http or https URL. (button_url has another scheme, no host, or resolves to a private or reserved address.)\n\ncomment_replies needs 1 to 3 public replies. (No non-blank reply, or more than three.)\n\npost_media must be a publicly reachable http or https URL. (post_media is not a public http or https URL.)\n\nfollow_to_unlock needs consent_dm_message, consent_button_title, opening_dm_message and cta_button_title. (mode is follow_to_unlock and one of the four texts is blank.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nDM automations work on Instagram business accounts only. (The account is a Facebook, LinkedIn or other non-Instagram-business account.)\n\nNo social accounts found. (The account row no longer exists in the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nThis social account is not part of the selected workspace. (workspace_id was given and the account is connected to another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The save failed inside the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/dm_automation_update": {
            "post": {
                "tags": [
                    "DM Automations"
                ],
                "summary": "Change an automation; fields left out keep their stored value.",
                "description": "Updates one automation. Send only the fields to change: every field of `/api/dm_automation_create` except `account_id` is accepted, and anything left out keeps its stored value (the account cannot be changed). The merged result is validated with the same rules as on create, so for example switching `mode` to `follow_to_unlock` needs the four follow-loop texts, and `all_posts` false needs a `post_id`.\n\nOwnership is checked before the body: Unlike create, the automation is looked up and its ownership checked first; field errors come after the 404 and 403 outcomes.\n\nStatus is not changed here: Use `/api/dm_automation_status` to pause or resume. An update keeps the current status.",
                "operationId": "dm_automation_update",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Plain numeric automation id.",
                                        "example": 91
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "New name.",
                                        "example": "Friday drop v2"
                                    },
                                    "all_posts": {
                                        "type": "boolean",
                                        "description": "Switch between all posts (true) and one post (false, with `post_id`).",
                                        "example": true
                                    },
                                    "post_id": {
                                        "type": "string",
                                        "description": "Instagram media id to watch when `all_posts` is false.",
                                        "example": "17895695668004550"
                                    },
                                    "post_type": {
                                        "type": "string",
                                        "description": "Media type of the watched post, display only.",
                                        "example": "reels"
                                    },
                                    "post_media": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "New thumbnail URL; must be publicly reachable. Sending the already stored value back is accepted unchanged.",
                                        "example": "https://scontent.cdninstagram.com/v/t51.29350-15/thumb.jpg"
                                    },
                                    "all_comments": {
                                        "type": "boolean",
                                        "description": "true to trigger on any comment; the stored keywords are then dropped.",
                                        "example": false
                                    },
                                    "keywords": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Replacement keyword list (array, JSON-encoded array string, or comma-separated string).",
                                        "example": [
                                            "price",
                                            "link",
                                            "cost"
                                        ]
                                    },
                                    "mode": {
                                        "type": "string",
                                        "description": "`anyone` or `follow_to_unlock`.",
                                        "enum": [
                                            "anyone",
                                            "follow_to_unlock"
                                        ],
                                        "example": "anyone"
                                    },
                                    "dm_message": {
                                        "type": "string",
                                        "description": "New direct message text. Cannot be blanked.",
                                        "example": "Updated: here is your link!"
                                    },
                                    "button_title": {
                                        "type": "string",
                                        "description": "New button label. To remove the button send both `button_title` and `button_url` as empty strings.",
                                        "example": "Shop now"
                                    },
                                    "button_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "New button link, publicly reachable http or https.",
                                        "example": "https://example.com/drop"
                                    },
                                    "comment_replies": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Replacement list of one to three public replies.",
                                        "example": [
                                            "Sent you a DM!"
                                        ]
                                    },
                                    "non_follower_comment_reply": {
                                        "type": "string",
                                        "description": "Public reply for non-followers.",
                                        "example": "Follow us and check your DMs!"
                                    },
                                    "consent_dm_message": {
                                        "type": "string",
                                        "description": "Follow-loop consent DM.",
                                        "example": "Follow us first and tap the button below."
                                    },
                                    "consent_button_title": {
                                        "type": "string",
                                        "description": "Follow-loop consent button label.",
                                        "example": "I follow you"
                                    },
                                    "opening_dm_message": {
                                        "type": "string",
                                        "description": "Follow-loop opening DM.",
                                        "example": "Welcome! Tap below once you follow."
                                    },
                                    "cta_button_title": {
                                        "type": "string",
                                        "description": "Follow-loop CTA button label.",
                                        "example": "Send my guide"
                                    },
                                    "unfollower_dm_message": {
                                        "type": "string",
                                        "description": "Follow-loop DM for users who still do not follow.",
                                        "example": "Looks like you are not following yet."
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 91
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Automation updated`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Automation updated"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or not a positive integer.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nSend all_posts as true, or post_id from dm_automation_posts. (The merged result watches neither all posts nor one post.)\n\nSend all_comments as true, or keywords (a list or comma-separated). (The merged result has neither all_comments nor keywords.)\n\nmode must be anyone or follow_to_unlock. (mode is another word.)\n\ndm_message is required. (dm_message was sent blank.)\n\nbutton_title and button_url go together. (After merging, exactly one of the two button fields is blank.)\n\nbutton_url must be a publicly reachable http or https URL. (button_url is not a public http or https URL.)\n\ncomment_replies needs 1 to 3 public replies. (The sent list is empty or longer than three.)\n\npost_media must be a publicly reachable http or https URL. (A new post_media value is not a public http or https URL.)\n\nfollow_to_unlock needs consent_dm_message, consent_button_title, opening_dm_message and cta_button_title. (The merged mode is follow_to_unlock and one of the four texts is blank.)\n\nNo automation found. (The automation disappeared between the ownership check and the save.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The automation's account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nAutomation not found. (No automation has this id.)\n\nThis social account is not part of the selected workspace. (workspace_id was given and the automation's account is connected to another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The save failed inside the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/dm_automation_delete": {
            "post": {
                "tags": [
                    "DM Automations"
                ],
                "summary": "Delete an automation.",
                "description": "Deletes the automation permanently. Its past counters stay visible in `/api/dm_automation_stats` until the 90-day retention drops them.",
                "operationId": "dm_automation_delete",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Plain numeric automation id.",
                                        "example": 91
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id"
                                ],
                                "example": {
                                    "id": 91
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Automation deleted`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Automation deleted"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (id is missing or not a positive integer.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The automation's account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nAutomation not found. (No automation has this id.)\n\nThis social account is not part of the selected workspace. (workspace_id was given and the automation's account is connected to another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The delete failed inside the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/dm_automation_status": {
            "post": {
                "tags": [
                    "DM Automations"
                ],
                "summary": "Pause or resume an automation.",
                "description": "Sets the automation to `active` (running) or `paused` (switched off). The third status word the API reads back, `pending`, is set by the app and cannot be requested here.",
                "operationId": "dm_automation_status",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Plain numeric automation id.",
                                        "example": 91
                                    },
                                    "status": {
                                        "type": "string",
                                        "description": "`active` to run the automation, `paused` to stop it. Case-insensitive.",
                                        "enum": [
                                            "active",
                                            "paused"
                                        ],
                                        "example": "paused"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "id",
                                    "status"
                                ],
                                "example": {
                                    "id": 91,
                                    "status": "paused"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Automation active` or `Automation paused`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Automation paused"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "status must be active or paused. (status is missing or another word. Checked before the id.)\n\nBad Request Please try again later (id is missing or not a positive integer.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nNo automation found. (The automation disappeared between the ownership check and the update.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The automation's account does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (workspace_id names a workspace you are not an active member of.)\n\nAutomation not found. (No automation has this id.)\n\nThis social account is not part of the selected workspace. (workspace_id was given and the automation's account is connected to another workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The update failed inside the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/report_account": {
            "post": {
                "tags": [
                    "Reports"
                ],
                "summary": "Analytics for one social account, or the overview of every account in the workspace.",
                "description": "Returns the report the Reports page computes for the period. With `account_id` it is that account's network report; without it, the workspace overview across every account. The period is a named `period` (default `last_week`) or explicit `start_date` and `end_date`. Every report also covers the comparison window of equal length right before the period, so counters come as current and previous values.\nThe `report` object is the in-app report minus tokens, the account list and the fields already given in `account`. Its keys depend on the network; see the note below.\n\nReport keys per network: - Workspace overview (no account_id): `summary`, `top5_posts`, `all_top5_posts` plus `fb_`, `tw_`, `li_`, `gmb_`, `insta_`, `pinterest_`, `tiktok_`, `youtube_`, `threads_`, `bluesky_top5_posts`, `engagement_by_library_graph`, `per_account_table`, `link_tracking`, `link_clicks`, `yt_info_message`.\n- Facebook page: `summary`, `published_post_counts`, `top_countries`, `top_cities`, `audience_location_map`, `popular_post`, plus chart payloads.\n- Facebook group: `popular_post`, `post_engagements`, `publishing_behavior`, `published_post_counts`, `audience_engagement`.\n- X (Twitter): `summary`, `summary_data`, `published_post_counts`, `audience_engagement`, `quote_tweets`, `bookmark_stats`, `best_time_insight`, `popular_post`, `chart_labels` with `daily_*` series, `heatmap_series`, `last_refresh_time`, `uncovered_ranges`.\n- LinkedIn company: `summary`, `audience_growth`, `engagement_table`, `impressions_table`, `pageviews_table`, `publishing_table`, `conversion`, `content_type`, `funnel_data`, `reaction_breakdown`, `follower_demo`, `visitor_demo`, `best_time_insight`, `popular_post`, `current_followers`, `chart_labels` with `daily_*` series.\n- LinkedIn profile: `summary`, `content_mix_rows`, `content_type_rows`, `publishing_rows`, `posts`, `recent_posts_total`, `best_time_insight`.\n- Instagram: `summary`, `reach`, `views`, `interactions`, `accounts_engaged` (each with its `prev_` twin), `daily_reach`, `reach_by_*`, `content_performance_by_media_type`, `engagement_breakdown_cur`, `audience_data_by_age`, `_by_gender`, `_by_city`, `_by_country`, `follower_demographics`, `profile_taps_by_contact_button`, `recent_posts`, `reel_rows`, `story_views`, `story_reach`, `published_post_counts`.\n- Pinterest: `analytics`, `account`, `split_device`, `split_format`, `top_posts`, `best_time_pins`, `boards`, `audience`, `published_pins_list`.\n- TikTok: `summary`, `popular_post`, `engagement_breakdown`, `duration_breakdown`, `caption_length`, `hashtag_performance`, `aspect_ratio`, `mention_network`, `day_of_week`, `heatmap_series`, `chart_labels` with `daily_*` series.\n- YouTube: `summary`, `channel_statistics`, `subscriber_count`, `total_videos`, `total_views`, `lifetime_watch_time_hours`, `top_posts`, `audience_countries`, `audience_cities`, `funnel_rows`, `traffic_sources_table`, `content_type_table`, `subscriber_sources_table`.\n- Threads: `summary`, `page_impressions`, `audience_engagement`, `published_post_counts`, `popular_post`, `engagement_breakdown`, `content_mix`, `content_performance`, `funnel_data`, `demographics_*`, `top_countries`, `top_cities`, `reach_rate_stats`, `best_time_insight`, `chart_labels` with `daily_*` series.\n- Bluesky: `summary`, `profile_overview`, `follower_growth`, `engagement_per_post`, `content_type_breakdown`, `publishing_behavior`, `funnel_stages`, `follow_ratio_stats`, `recent_posts`, `popular_post`, `mentions_list`, `new_followers_list`, `activity_feed`, `chart_labels` with `daily_*` series.\n\nChart payloads (`*_chart`, `*_option`) are ECharts option objects as drawn in the app. Google Business accounts answer the in-app Google Business report. Facebook profiles and Instagram accounts connected the old way have no report and answer an empty `report`.\n\nLive network calls: The report is fetched from the network at call time and can take 10 to 60 seconds for a long period. Cache on your side; do not poll.",
                "operationId": "report_account",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted social account id from `/api/social_account_list`. Leave out for the overview of every account in the workspace.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "period": {
                                        "type": "string",
                                        "description": "Named window in the workspace owner's timezone: `today`, `yesterday`, `last_week` (the 7 days before today) or `last_month` (the last 30 days including today). Ignored when dates are sent.",
                                        "enum": [
                                            "today",
                                            "yesterday",
                                            "last_week",
                                            "last_month"
                                        ],
                                        "default": "last_week",
                                        "example": "last_week"
                                    },
                                    "start_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "First day of the period, `YYYY-MM-DD`. Sent together with `end_date`; at most 366 days apart.",
                                        "example": "2026-10-01"
                                    },
                                    "end_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Last day of the period, `YYYY-MM-DD`, not before `start_date`.",
                                        "example": "2026-10-21"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7xQ2pL9k=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "account": {
                                            "type": "object",
                                            "description": "`{id, name, network}` of the reported account (encrypted id), or `null` for the workspace overview."
                                        },
                                        "period": {
                                            "type": "object",
                                            "properties": {
                                                "start": {
                                                    "type": "string",
                                                    "format": "date",
                                                    "description": "First day of the period."
                                                },
                                                "end": {
                                                    "type": "string",
                                                    "format": "date",
                                                    "description": "Last day of the period."
                                                },
                                                "compare_start": {
                                                    "type": "string",
                                                    "format": "date",
                                                    "description": "First day of the comparison window."
                                                },
                                                "compare_end": {
                                                    "type": "string",
                                                    "format": "date",
                                                    "description": "Last day of the comparison window."
                                                }
                                            }
                                        },
                                        "report": {
                                            "type": "object",
                                            "description": "The network's report. Counters are objects `{cur_count, prev_count, percentage, flag}` where `flag` is `up` or `down` against the comparison window; daily series are arrays aligned with `chart_labels`; `popular_post` lists the period's posts with their metrics.",
                                            "properties": {
                                                "summary": {
                                                    "type": "object",
                                                    "description": "The headline counters of the network (followers, posts, engagement, impressions and so on)."
                                                },
                                                "popular_post": {
                                                    "type": "array",
                                                    "items": [],
                                                    "description": "Posts of the period, most engaged first, each with the network's per-post metrics (likes, comments, shares, views, reach, link, image, date). Present on most networks."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "account": {
                                        "id": "nX2k9Qp7Lw==",
                                        "name": "Acme Page",
                                        "network": "facebook"
                                    },
                                    "period": {
                                        "start": "2026-10-01",
                                        "end": "2026-10-21",
                                        "compare_start": "2026-09-10",
                                        "compare_end": "2026-09-30"
                                    },
                                    "report": {
                                        "summary": {
                                            "total_followers": {
                                                "cur_count": 12840,
                                                "prev_count": 12610,
                                                "percentage": 1.82,
                                                "flag": "up"
                                            },
                                            "total_posts": {
                                                "cur_count": 18,
                                                "prev_count": 15,
                                                "percentage": 20,
                                                "flag": "up"
                                            },
                                            "post_engagement": {
                                                "cur_count": 2310,
                                                "prev_count": 2544,
                                                "percentage": -9.2,
                                                "flag": "down"
                                            },
                                            "comments": {
                                                "cur_count": 164,
                                                "prev_count": 120,
                                                "percentage": 36.67,
                                                "flag": "up"
                                            }
                                        },
                                        "published_post_counts": {
                                            "photo": 10,
                                            "video": 3,
                                            "link": 4,
                                            "status": 1
                                        },
                                        "top_countries": [
                                            {
                                                "name": "United States",
                                                "value": 6420
                                            }
                                        ],
                                        "top_cities": [
                                            {
                                                "name": "New York",
                                                "value": 980
                                            }
                                        ],
                                        "popular_post": [
                                            {
                                                "post_id": "1029384756_7788990011",
                                                "message": "Three ways to plan a month of posts in an hour",
                                                "image": "https://scontent.example.com/plan.jpg",
                                                "type": "photo",
                                                "date": "21 October 2026, 09:30 AM UTC",
                                                "likes": 210,
                                                "comments": 18,
                                                "share": 12,
                                                "views": 0,
                                                "reach": 5400,
                                                "engagement": 240,
                                                "url": "https://www.facebook.com/1029384756_7788990011"
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (account_id was sent but does not decrypt to one account id.)\n\nperiod must be today, yesterday, last_week or last_month, or send start_date and end_date as YYYY-MM-DD at most 366 days apart. (Unknown period, a malformed date, end_date before start_date, or more than 366 days.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account belongs to another user or no longer exists for the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account, although the owner's, is not attached to that workspace.)\n\nNo social account available. (The account is not visible to the report (for example not in the workspace's account list).)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This account needs to be reconnected in RecurPost before its report can be read. (The account's token has expired or the network refused it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "411": {
                        "description": "X (Twitter) analytics are fetched on demand and paid for from your X Wallet. Generate your first report to get started. (An X account whose report has never been generated in the app.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The network or the app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/report_posts": {
            "post": {
                "tags": [
                    "Reports"
                ],
                "summary": "Metrics per published post of one account over the period.",
                "description": "Returns the per-post metrics of one account for the period, the partner of `/api/history_list`: the posts the network reports for the window, with likes, comments, shares, views, reach and the network's link, most engaged first. The period and the comparison window are the same as in `/api/report_account`.\n\nNetworks with a per-post report: Facebook pages, X, LinkedIn profiles and companies, Pinterest, Instagram, TikTok, YouTube, Threads and Bluesky. Facebook profiles and groups and Google Business have none and answer an empty `posts` object.\n\nMetrics are the network's: The posts and numbers come from the network's own API for the window, so the list can differ from `/api/history_list` (posts made outside RecurPost appear, posts the network has not indexed yet do not).",
                "operationId": "report_posts",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted social account id from `/api/social_account_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "period": {
                                        "type": "string",
                                        "description": "Named window in the workspace owner's timezone: `today`, `yesterday`, `last_week` or `last_month`. Ignored when dates are sent.",
                                        "enum": [
                                            "today",
                                            "yesterday",
                                            "last_week",
                                            "last_month"
                                        ],
                                        "default": "last_week",
                                        "example": "last_week"
                                    },
                                    "start_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "First day of the period, `YYYY-MM-DD`. Sent together with `end_date`; at most 366 days apart.",
                                        "example": "2026-10-01"
                                    },
                                    "end_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Last day of the period, `YYYY-MM-DD`, not before `start_date`.",
                                        "example": "2026-10-21"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7xQ2pL9k=="
                                    }
                                },
                                "required": [
                                    "account_id"
                                ],
                                "example": {
                                    "account_id": "nX2k9Qp7Lw=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "account": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted social account id."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Account name."
                                                },
                                                "network": {
                                                    "type": "string",
                                                    "description": "Network key, as in `/api/queue_list`."
                                                }
                                            }
                                        },
                                        "period": {
                                            "type": "object",
                                            "description": "`{start, end, compare_start, compare_end}` as `YYYY-MM-DD`."
                                        },
                                        "posts": {
                                            "type": "object",
                                            "properties": {
                                                "popular_post": {
                                                    "type": "array",
                                                    "items": [],
                                                    "description": "The period's posts, most engaged first. Each carries the network's per-post fields; on Facebook pages for example `post_id`, `message`, `image`, `type`, `date`, `created_stamp`, `likes`, `comments`, `share`, `views`, `reach`, `link_clicks`, `other_clicks`, `engagement`, `url`, `video_src`, `video_embed`. Other networks use their own names (for example `retweets`, `impressions`, `saves`, `pin_metrics`)."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "account": {
                                        "id": "nX2k9Qp7Lw==",
                                        "name": "Acme Page",
                                        "network": "facebook"
                                    },
                                    "period": {
                                        "start": "2026-10-01",
                                        "end": "2026-10-21",
                                        "compare_start": "2026-09-10",
                                        "compare_end": "2026-09-30"
                                    },
                                    "posts": {
                                        "popular_post": [
                                            {
                                                "post_id": "1029384756_7788990011",
                                                "message": "Three ways to plan a month of posts in an hour",
                                                "image": "https://scontent.example.com/plan.jpg",
                                                "type": "photo",
                                                "date": "21 October 2026, 09:30 AM UTC",
                                                "created_stamp": 1792575000,
                                                "likes": 210,
                                                "comments": 18,
                                                "share": 12,
                                                "views": 0,
                                                "reach": 5400,
                                                "link_clicks": 44,
                                                "other_clicks": 97,
                                                "engagement": 240,
                                                "url": "https://www.facebook.com/1029384756_7788990011",
                                                "video_src": "",
                                                "video_embed": ""
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (account_id is missing or does not decrypt to one account id.)\n\nperiod must be today, yesterday, last_week or last_month, or send start_date and end_date as YYYY-MM-DD at most 366 days apart. (Unknown period, a malformed date, end_date before start_date, or more than 366 days.)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account belongs to another user or does not exist.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No social account available. (The account is not visible to the report.)\n\nWorkspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nThis social account is not part of the selected workspace. (The account is the owner's but is not linked to the workspace named in workspace_id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This account needs to be reconnected in RecurPost before its report can be read. (The account's token has expired or the network refused it.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The network or the app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/report_pdf": {
            "post": {
                "tags": [
                    "Reports"
                ],
                "summary": "The account or post report as a PDF, produced now or emailed.",
                "description": "Produces the Reports page as a PDF. `type` `account` renders one account's report, or the workspace overview when `id` is left out; `type` `posts` renders the per-post report of one account. Same `period` or dates as the other report calls.\nWithout `email` the PDF is generated inside the request and its URL returned. With `email` (one or several addresses) the app generates it in the background and mails the link; the all-accounts report cannot be emailed.\n\nSlow without email: Without `email` the network is read and the PDF rendered inside the request, often 30 seconds or more. Prefer `email` for long periods, or raise your client timeout.\n\nEmailed reports: With `email` the app queues the job and answers at once; the recipients get the link when the PDF is ready. Nothing is returned to poll.",
                "operationId": "report_pdf",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "description": "`account` for the account (or overview) report, `posts` for the per-post report.",
                                        "enum": [
                                            "account",
                                            "posts"
                                        ],
                                        "default": "account",
                                        "example": "account"
                                    },
                                    "id": {
                                        "type": "string",
                                        "description": "Encrypted social account id from `/api/social_account_list`. Required for `type` `posts` and whenever `email` is sent; leave out for the all-accounts overview.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "period": {
                                        "type": "string",
                                        "description": "Named window in the workspace owner's timezone: `today`, `yesterday`, `last_week` or `last_month`. Ignored when dates are sent.",
                                        "enum": [
                                            "today",
                                            "yesterday",
                                            "last_week",
                                            "last_month"
                                        ],
                                        "default": "last_week",
                                        "example": "last_month"
                                    },
                                    "start_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "First day of the period, `YYYY-MM-DD`. Sent together with `end_date`; at most 366 days apart.",
                                        "example": "2026-10-01"
                                    },
                                    "end_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Last day of the period, `YYYY-MM-DD`, not before `start_date`.",
                                        "example": "2026-10-21"
                                    },
                                    "email": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Address or addresses to mail the PDF link to: one address, a comma-separated list, a JSON array or a form array. When sent, no `pdf_url` is returned.",
                                        "example": [
                                            "reports@example.com"
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7xQ2pL9k=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`, or `The report will be emailed to a@example.com, b@example.com.` when email was sent."
                                        },
                                        "type": {
                                            "type": "string",
                                            "description": "`account` or `posts`."
                                        },
                                        "period": {
                                            "type": "object",
                                            "description": "`{start, end, compare_start, compare_end}` as `YYYY-MM-DD`."
                                        },
                                        "pdf_url": {
                                            "type": "string",
                                            "format": "uri",
                                            "description": "Download URL of the PDF. Only present without email."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "type": "account",
                                    "period": {
                                        "start": "2026-09-22",
                                        "end": "2026-10-22",
                                        "compare_start": "2026-08-22",
                                        "compare_end": "2026-09-21"
                                    },
                                    "pdf_url": "https://cdn.example.com/reports/acme-page-2026-10-22.pdf"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "type must be account or posts. (Another type was sent.)\n\nA valid id is required. (id was sent but does not decrypt to one account id.)\n\nThe posts report needs an account id. (type posts without id.)\n\nEmailing the report needs an account id; the all-accounts report is download only. (email without id.)\n\nemail holds an invalid address: ... (One of the addresses is not a valid email.)\n\nperiod must be today, yesterday, last_week or last_month, or send start_date and end_date as YYYY-MM-DD at most 366 days apart. (Unknown period, a malformed date, end_date before start_date, or more than 366 days.)\n\nThe posts report is not available for this network. (type posts on a network without a per-post report (Facebook profiles and groups, Google Business, Instagram accounts connected the old way).)\n\nInvalid workspace_id. (workspace_id does not decrypt to an id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account belongs to another user or does not exist.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Social account not found. (The account no longer exists for the owner.)\n\nWorkspace not found or you do not have access to it. (The workspace does not exist or you are not an active member of it.)\n\nThis social account is not part of the selected workspace. (The account is the owner's but is not linked to the workspace named in workspace_id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This account needs to be reconnected in RecurPost before its report can be read. (The account is marked as needing reconnection.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The report could not be produced. (The app did not return a PDF URL (or did not accept the email job); a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/report_pins": {
            "post": {
                "tags": [
                    "Reports"
                ],
                "summary": "The pins of a Pinterest board with their metrics, and the board's daily impressions, saves and clicks over the period.",
                "description": "Returns, for one Pinterest account, the pins of a board with Pinterest's per-pin metrics and the board's day-by-day impressions, saves and pin clicks for the period, as the in-app Pinterest report shows them. By default the board is the one the account was connected with; `board_id` picks another board of the same Pinterest profile.\nThe pin list is the board's own (up to 100 pins, Pinterest's page) and its metrics are Pinterest's 90-day pin metrics, so they are not limited to the period; the `daily` rows are limited to the period and add up the ten pins with the most impressions.\n\nPin metrics are not period metrics: Pinterest hands out 90-day (or lifetime) metrics per pin, so the `pins` numbers do not change with `period`. Only `daily` follows the period.\n\nLive network calls: The board and its pins are read from Pinterest at call time, one metrics call per top pin; expect several seconds. Cache on your side.",
                "operationId": "report_pins",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted id of a Pinterest account from `/api/social_account_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "board_id": {
                                        "type": "string",
                                        "description": "Plain Pinterest board id (digits only; other characters are dropped). Defaults to the board the account was connected with.",
                                        "example": "1125376489201"
                                    },
                                    "period": {
                                        "type": "string",
                                        "description": "Named window in the workspace owner's timezone: `today`, `yesterday`, `last_week` (the 7 days before today) or `last_month` (the last 30 days including today). Ignored when dates are sent.",
                                        "enum": [
                                            "today",
                                            "yesterday",
                                            "last_week",
                                            "last_month"
                                        ],
                                        "default": "last_week",
                                        "example": "last_week"
                                    },
                                    "start_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "First day of the period, `YYYY-MM-DD`. Sent together with `end_date`; at most 366 days apart.",
                                        "example": "2026-10-01"
                                    },
                                    "end_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Last day of the period, `YYYY-MM-DD`, not before `start_date`.",
                                        "example": "2026-10-21"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7xQ2pL9k=="
                                    }
                                },
                                "required": [
                                    "account_id"
                                ],
                                "example": {
                                    "account_id": "nX2k9Qp7Lw=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "account": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted social account id, as sent."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Account name."
                                                },
                                                "network": {
                                                    "type": "string",
                                                    "description": "`pinterest`."
                                                }
                                            }
                                        },
                                        "board_id": {
                                            "type": "string",
                                            "description": "The board the pins were read from."
                                        },
                                        "period": {
                                            "type": "object",
                                            "description": "`{start, end, compare_start, compare_end}` as `YYYY-MM-DD`."
                                        },
                                        "pins": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "The board's pins as Pinterest lists them.",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "description": "Pinterest pin id."
                                                    },
                                                    "title": {
                                                        "type": "string",
                                                        "description": "Pin title."
                                                    },
                                                    "description": {
                                                        "type": "string",
                                                        "description": "Pin description."
                                                    },
                                                    "link": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Destination link of the pin."
                                                    },
                                                    "image": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "600px image when Pinterest has one, otherwise the original or the first size available."
                                                    },
                                                    "created_at": {
                                                        "type": "string",
                                                        "description": "Creation time as Pinterest reports it (ISO 8601)."
                                                    },
                                                    "impressions": {
                                                        "type": "integer",
                                                        "description": "90-day impressions (lifetime when the 90-day set is missing)."
                                                    },
                                                    "saves": {
                                                        "type": "integer",
                                                        "description": "90-day saves."
                                                    },
                                                    "clicks": {
                                                        "type": "integer",
                                                        "description": "90-day pin clicks."
                                                    },
                                                    "outbound_clicks": {
                                                        "type": "integer",
                                                        "description": "90-day outbound clicks."
                                                    }
                                                }
                                            }
                                        },
                                        "daily": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "One row per day of the period, oldest first.",
                                                "properties": {
                                                    "date": {
                                                        "type": "string",
                                                        "format": "date",
                                                        "description": "The day."
                                                    },
                                                    "impressions": {
                                                        "type": "integer",
                                                        "description": "Impressions of the top ten pins that day."
                                                    },
                                                    "saves": {
                                                        "type": "integer",
                                                        "description": "Saves that day."
                                                    },
                                                    "clicks": {
                                                        "type": "integer",
                                                        "description": "Pin clicks that day."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "account": {
                                        "id": "nX2k9Qp7Lw==",
                                        "name": "Acme Recipes",
                                        "network": "pinterest"
                                    },
                                    "board_id": "1125376489201",
                                    "period": {
                                        "start": "2026-10-01",
                                        "end": "2026-10-21",
                                        "compare_start": "2026-09-10",
                                        "compare_end": "2026-09-30"
                                    },
                                    "pins": [
                                        {
                                            "id": "98765432109876543",
                                            "title": "One-pan lemon chicken",
                                            "description": "A 30 minute weeknight dinner.",
                                            "link": "https://acme.example/recipes/lemon-chicken",
                                            "image": "https://i.pinimg.com/600x/ab/cd/ef.jpg",
                                            "created_at": "2026-09-28T14:02:11",
                                            "impressions": 4120,
                                            "saves": 96,
                                            "clicks": 310,
                                            "outbound_clicks": 142
                                        }
                                    ],
                                    "daily": [
                                        {
                                            "date": "2026-10-01",
                                            "impressions": 210,
                                            "saves": 4,
                                            "clicks": 17
                                        },
                                        {
                                            "date": "2026-10-02",
                                            "impressions": 188,
                                            "saves": 6,
                                            "clicks": 12
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "account_id is required. (account_id is missing or does not decrypt to one account id.)\n\nperiod must be today, yesterday, last_week or last_month, or send start_date and end_date as YYYY-MM-DD at most 366 days apart. (Unknown period, a malformed date, end_date before start_date, or more than 366 days.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nThis report is for Pinterest accounts. (The account is not a Pinterest account.)\n\nboard_id is required for this account. (No board_id was sent and the account has no board of its own recorded.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account belongs to another user or no longer exists for the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account, although the owner's, is not attached to that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This account needs to be reconnected in RecurPost before its report can be read. (The account is marked as needing reconnection.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "502": {
                        "description": "Pinterest did not answer. (Pinterest refused or failed the board read; Pinterest's own message replaces the default when the app relayed one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/report_ads": {
            "post": {
                "tags": [
                    "Reports"
                ],
                "summary": "Paid ads analytics of a Facebook page, Instagram business or LinkedIn company account over the period, as data or as a PDF.",
                "description": "Returns the in-app Paid Ads report for one account over the period: spend, reach, impressions, clicks, CTR, CPC and CPM against the comparison window, the top campaigns and ads, and the campaign, ad set (or campaign group) and ad tables. The account must be a Facebook page, an Instagram business account or a LinkedIn company page, and the ad account it reports on is one of the ad accounts that social account can see; `ads_account_id` picks one, the app's default otherwise.\nThe workspace owner's plan must carry the Paid Ads add-on; the owner's add-on pays for every member's call. `format=pdf` renders the same report to a PDF and returns its URL instead of the data.\n\nPaid Ads add-on required: The add-on is read on the workspace owner, not on the caller. A member of a workspace whose owner has no add-on gets the 403 even if the member's own plan has one.\n\nReport keys per network: - Facebook page and Instagram business: `summary`, `page_impressions_reach_data`, `cpc_data`, `spent_data`, `age_gender_spend_data`, `age_gender_reach_data`, `age_gender_impressions_data`, `top3_campaigns`, `top6_ads`, `campaigns`, `adsets`, `ads`, `funnel_rows`, `placement_rows`, `device_rows`, `datewise`.\n- LinkedIn company: `summary`, `page_impressions_reach_data`, `cpc_data`, `spent_data`, the three `age_gender_*` keys (empty on LinkedIn), `top3_campaigns`, `top6_ads`, `campaigns`, `campaign_groups`, `ads`.\n\nChart payloads are the option objects the app draws. Amounts are in `ads_account.currency`.\n\nLive network calls: The report is fetched from the ad platform at call time and can take 10 to 60 seconds; the PDF longer. Cache on your side; do not poll.",
                "operationId": "report_ads",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted id of a Facebook page, Instagram business or LinkedIn company account from `/api/social_account_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "ads_account_id": {
                                        "type": "string",
                                        "description": "The ad account to report on, one of the ids listed in `ads_accounts` of a previous answer (letters, digits and underscore; anything else is dropped). Defaults to the account the app selects.",
                                        "example": "act_1029384756"
                                    },
                                    "format": {
                                        "type": "string",
                                        "description": "`json` for the data, `pdf` for a PDF of the report. Case-insensitive.",
                                        "enum": [
                                            "json",
                                            "pdf"
                                        ],
                                        "default": "json",
                                        "example": "json"
                                    },
                                    "period": {
                                        "type": "string",
                                        "description": "Named window in the workspace owner's timezone: `today`, `yesterday`, `last_week` (the 7 days before today) or `last_month` (the last 30 days including today). Ignored when dates are sent.",
                                        "enum": [
                                            "today",
                                            "yesterday",
                                            "last_week",
                                            "last_month"
                                        ],
                                        "default": "last_week",
                                        "example": "last_week"
                                    },
                                    "start_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "First day of the period, `YYYY-MM-DD`. Sent together with `end_date`; at most 366 days apart.",
                                        "example": "2026-10-01"
                                    },
                                    "end_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Last day of the period, `YYYY-MM-DD`, not before `start_date`.",
                                        "example": "2026-10-21"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7xQ2pL9k=="
                                    }
                                },
                                "required": [
                                    "account_id"
                                ],
                                "example": {
                                    "account_id": "nX2k9Qp7Lw=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "account": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted social account id, as sent."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Account name."
                                                },
                                                "network": {
                                                    "type": "string",
                                                    "description": "`facebook`, `instagram` or `linkedin`."
                                                }
                                            }
                                        },
                                        "period": {
                                            "type": "object",
                                            "description": "`{start, end, compare_start, compare_end}` as `YYYY-MM-DD`."
                                        },
                                        "ads_account": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "The ad account reported on. Data format only."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Its name."
                                                },
                                                "currency": {
                                                    "type": "string",
                                                    "description": "Currency code of the spend figures, for example `USD`."
                                                }
                                            }
                                        },
                                        "ads_accounts": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Every ad account the social account can report on, each `{id, name, currency}` (Facebook and Instagram answer the app's own account rows, which carry at least `id` and `name`). Data format only."
                                            }
                                        },
                                        "report": {
                                            "type": "object",
                                            "description": "The ads report minus the fields given above. `summary` holds `total_active_campaigns`, `spend`, `reach`, `impressions`, `clicks`, `ctr`, `cpc` and `cpm` as `{cur_count, prev_count, percentage, flag}`; see the note for the other keys. Data format only."
                                        },
                                        "pdf_url": {
                                            "type": "string",
                                            "format": "uri",
                                            "description": "Download URL of the PDF. PDF format only."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "account": {
                                        "id": "nX2k9Qp7Lw==",
                                        "name": "Acme Page",
                                        "network": "facebook"
                                    },
                                    "period": {
                                        "start": "2026-10-01",
                                        "end": "2026-10-21",
                                        "compare_start": "2026-09-10",
                                        "compare_end": "2026-09-30"
                                    },
                                    "ads_account": {
                                        "id": "act_1029384756",
                                        "name": "Acme Main",
                                        "currency": "USD"
                                    },
                                    "ads_accounts": [
                                        {
                                            "id": "act_1029384756",
                                            "name": "Acme Main",
                                            "currency": "USD"
                                        }
                                    ],
                                    "report": {
                                        "summary": {
                                            "total_active_campaigns": {
                                                "cur_count": 3,
                                                "prev_count": 2,
                                                "percentage": 50,
                                                "flag": "up"
                                            },
                                            "spend": {
                                                "cur_count": 412.75,
                                                "prev_count": 380.1,
                                                "percentage": 8.59,
                                                "flag": "up"
                                            },
                                            "reach": {
                                                "cur_count": 58120,
                                                "prev_count": 61400,
                                                "percentage": -5.34,
                                                "flag": "down"
                                            },
                                            "impressions": {
                                                "cur_count": 142300,
                                                "prev_count": 139800,
                                                "percentage": 1.79,
                                                "flag": "up"
                                            },
                                            "clicks": {
                                                "cur_count": 2210,
                                                "prev_count": 1980,
                                                "percentage": 11.62,
                                                "flag": "up"
                                            },
                                            "ctr": {
                                                "cur_count": 1.55,
                                                "prev_count": 1.42,
                                                "percentage": 9.15,
                                                "flag": "up"
                                            },
                                            "cpc": {
                                                "cur_count": 0.19,
                                                "prev_count": 0.19,
                                                "percentage": 0,
                                                "flag": "up"
                                            },
                                            "cpm": {
                                                "cur_count": 2.9,
                                                "prev_count": 2.72,
                                                "percentage": 6.62,
                                                "flag": "up"
                                            }
                                        },
                                        "top3_campaigns": [
                                            {
                                                "name": "Autumn launch",
                                                "spend": 210.4,
                                                "clicks": 1320
                                            }
                                        ],
                                        "campaigns": [
                                            {
                                                "name": "Autumn launch",
                                                "status": "ACTIVE",
                                                "spend": 210.4,
                                                "impressions": 71000,
                                                "clicks": 1320
                                            }
                                        ],
                                        "datewise": [
                                            {
                                                "date": "2026-10-01",
                                                "spend": 18.2,
                                                "impressions": 6400,
                                                "clicks": 98
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "account_id is required. (account_id is missing or does not decrypt to one account id.)\n\nperiod must be today, yesterday, last_week or last_month, or send start_date and end_date as YYYY-MM-DD at most 366 days apart. (Unknown period, a malformed date, end_date before start_date, or more than 366 days.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nAds reports cover Facebook pages, Instagram business and LinkedIn company accounts. (The account is of another network or kind (for example a Facebook group or a LinkedIn profile).)\n\nformat must be json or pdf. (Another format was sent.)\n\nThe ads report PDF could not be produced. (PDF format: the app answered without a PDF URL. When the app reported a failure the status and message are the app's.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account belongs to another user or no longer exists for the workspace owner.)\n\nThe workspace owner's plan has no Paid Ads add-on; the ads report needs one. (The owner's plan carries no Paid Ads add-on. Checked after the account and period checks.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account, although the owner's, is not attached to that workspace.)\n\nNo social account available. (The account is not visible to the report.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This account needs to be reconnected in RecurPost before its report can be read. (The account is marked as needing reconnection.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (Data format: the network or the app did not answer; a message from the app replaces the default when it sent one.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/report_x": {
            "post": {
                "tags": [
                    "Reports"
                ],
                "summary": "Price, then buy, the X (Twitter) analytics of an account for a period; paid from the caller's X Wallet.",
                "description": "X analytics are not free: RecurPost fetches them on demand and bills the fetch to an X Wallet. This call is the two-step purchase behind the in-app X report. `action=quote` (the default) prices the period: which parts are already stored (free), what the rest costs per post and for the account overview, the cap on the charge and whether the wallet can cover it. `action=fetch` with `confirm=true` reserves the capped amount, fetches and stores the data, charges what was used and refunds the rest. `/api/report_account` and `/api/report_posts` then read the stored data for that account at no cost.\nThe wallet charged is the one of the account that owns the API key you call with (`wallet` answers `caller`), even when the workspace belongs to someone else. `force_refresh=true` fetches again what is already stored, and pays for it again.\n\nfetch charges real money: A fetch with `confirm=true` debits the X Wallet of the API key's owner (the caller, not the workspace owner). Always quote first, check `sufficient` and `max_charge`, and never retry a fetch in a loop: a repeat is free only while `covered` is `true` and `force_refresh` is off.\n\nReading the data afterwards: The stored data is what `/api/report_account` and `/api/report_posts` answer for an X account (their 411 means nothing has been fetched yet). The quote's `uncovered_ranges` also appears in the account report as the parts still missing.",
                "operationId": "report_x",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted id of an X account from `/api/social_account_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "action": {
                                        "type": "string",
                                        "description": "`quote` prices the period without charging; `fetch` charges the wallet and stores the data. Case-insensitive.",
                                        "enum": [
                                            "quote",
                                            "fetch"
                                        ],
                                        "default": "quote",
                                        "example": "quote"
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Required when action is `fetch`: send `true` to accept the charge. Ignored for `quote`.",
                                        "example": true
                                    },
                                    "force_refresh": {
                                        "type": "boolean",
                                        "description": "`true` fetches (and pays for) the whole period again, replacing what is stored. Sent on both actions; on `quote` it prices the full refetch.",
                                        "default": "false",
                                        "example": false
                                    },
                                    "period": {
                                        "type": "string",
                                        "description": "Named window in the workspace owner's timezone: `today`, `yesterday`, `last_week` (the 7 days before today) or `last_month` (the last 30 days including today). Ignored when dates are sent.",
                                        "enum": [
                                            "today",
                                            "yesterday",
                                            "last_week",
                                            "last_month"
                                        ],
                                        "default": "last_week",
                                        "example": "last_month"
                                    },
                                    "start_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "First day of the period, `YYYY-MM-DD`. Sent together with `end_date`; at most 366 days apart.",
                                        "example": "2026-10-01"
                                    },
                                    "end_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Last day of the period, `YYYY-MM-DD`, not before `start_date`.",
                                        "example": "2026-10-21"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7xQ2pL9k=="
                                    }
                                },
                                "required": [
                                    "account_id"
                                ],
                                "example": {
                                    "account_id": "nX2k9Qp7Lw=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "account": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "Encrypted social account id, as sent."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Account name."
                                                },
                                                "network": {
                                                    "type": "string",
                                                    "description": "`twitter`."
                                                }
                                            }
                                        },
                                        "period": {
                                            "type": "object",
                                            "description": "`{start, end, compare_start, compare_end}` as `YYYY-MM-DD`."
                                        },
                                        "wallet": {
                                            "type": "string",
                                            "description": "`caller`: the X Wallet of the API key's owner is the one quoted and charged."
                                        },
                                        "covered": {
                                            "type": "boolean",
                                            "description": "Quote: `true` when the whole period is already stored and a fetch would charge nothing."
                                        },
                                        "overview_needed": {
                                            "type": "boolean",
                                            "description": "Quote: `true` when the account overview (followers and profile counters) has to be fetched too."
                                        },
                                        "uncovered_ranges": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Quote: the date ranges not yet stored, as the app prints them, for example `01 Oct 2026 - 10 Oct 2026`."
                                            }
                                        },
                                        "per_post_cost": {
                                            "type": "number",
                                            "description": "Quote: price per post fetched, in the wallet's currency."
                                        },
                                        "overview_cost": {
                                            "type": "number",
                                            "description": "Quote: price of the account overview, when needed."
                                        },
                                        "max_posts": {
                                            "type": "integer",
                                            "description": "Quote: the most posts one fetch will read; older posts beyond it are left out (`truncated` on the fetch)."
                                        },
                                        "max_charge": {
                                            "type": "number",
                                            "description": "Quote: the cap reserved on the wallet before the fetch; the fetch charges at most this."
                                        },
                                        "balance": {
                                            "type": "number",
                                            "description": "Quote: the caller's wallet balance."
                                        },
                                        "sufficient": {
                                            "type": "boolean",
                                            "description": "Quote: `true` when `balance` covers `max_charge`."
                                        },
                                        "charged": {
                                            "type": "boolean",
                                            "description": "Fetch: `false` when the period was already stored and nothing was charged."
                                        },
                                        "amount_charged": {
                                            "type": "number",
                                            "description": "Fetch: what the wallet was charged after the refund of the unused reserve."
                                        },
                                        "posts_fetched": {
                                            "type": "integer",
                                            "description": "Fetch: posts read and stored."
                                        },
                                        "truncated": {
                                            "type": "boolean",
                                            "description": "Fetch: `true` when the period held more posts than `max_posts`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "account": {
                                        "id": "nX2k9Qp7Lw==",
                                        "name": "@acmecoffee",
                                        "network": "twitter"
                                    },
                                    "period": {
                                        "start": "2026-09-22",
                                        "end": "2026-10-22",
                                        "compare_start": "2026-08-22",
                                        "compare_end": "2026-09-21"
                                    },
                                    "wallet": "caller",
                                    "covered": false,
                                    "overview_needed": true,
                                    "uncovered_ranges": [
                                        "22 Sep 2026 - 22 Oct 2026"
                                    ],
                                    "per_post_cost": 0.006,
                                    "overview_cost": 0.012,
                                    "max_posts": 200,
                                    "max_charge": 1.22,
                                    "balance": 5,
                                    "sufficient": true
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "account_id is required. (account_id is missing or does not decrypt to one account id.)\n\nperiod must be today, yesterday, last_week or last_month, or send start_date and end_date as YYYY-MM-DD at most 366 days apart. (Unknown period, a malformed date, end_date before start_date, or more than 366 days.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nThis call is for X accounts. (The account is not an X account.)\n\naction must be quote or fetch. (Another action was sent.)\n\nSend confirm=true to charge your X wallet and fetch the data. (action fetch without confirm=true.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "402": {
                        "description": "Your X wallet balance of 0.50 is below the 1.22 this fetch may cost; top it up in RecurPost. (Fetch: the balance is below the capped charge; the two amounts are the caller's balance and the cap.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account belongs to another user or no longer exists for the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account, although the owner's, is not attached to that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This account needs to be reconnected in RecurPost before its report can be read. (The account is marked as needing reconnection.)\n\nThis account needs to be reconnected in RecurPost before its data can be fetched. (Fetch: X refused the account's token (401). Nothing was charged.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "X is rate limiting this account; try again later. Nothing was charged. (Fetch: X rate limited the account.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The quote could not be read. (Quote: the app did not price the period; the status and message are the app's when it sent any.)\n\nThe fetch failed; the reserve was refunded. (Fetch: any other failure; the status and message are the app's when it sent any. The reserved amount is given back.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/report_labels": {
            "post": {
                "tags": [
                    "Reports"
                ],
                "summary": "Engagement of the published posts by post label over the period, or the published posts of one label.",
                "description": "Sums, for every post label of the workspace owner, the posts published in the period and their likes, comments, shares and clicks, with the best post of each label and an eight-point trend across the period. Only posts that were actually published (not failed, not still queued) count, and a post counts once per account it went out on.\nWith `label_id` the call lists that label's published posts instead, newest first and paged.\n\nCounts come from the app's own metrics: Likes, comments and shares are the counters RecurPost has collected for each published post, refreshed by its background jobs, not a live read from the networks; clicks are the clicks on the post's RecurPost-tracked link. Labels are kept per account owner, so every workspace of the owner shares the same labels and the report is not narrowed to the workspace sent.",
                "operationId": "report_labels",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "label_id": {
                                        "type": "integer",
                                        "description": "Plain id of a post label from `/api/post_labels`. When sent, the answer is that label's published posts of the period instead of the summary.",
                                        "example": 12
                                    },
                                    "page": {
                                        "type": "integer",
                                        "description": "Page of the post list, from 1. Used with `label_id` only.",
                                        "default": "1",
                                        "example": 1
                                    },
                                    "per_page": {
                                        "type": "integer",
                                        "description": "Posts per page, 1 to 50. Used with `label_id` only.",
                                        "default": "20",
                                        "example": 20
                                    },
                                    "period": {
                                        "type": "string",
                                        "description": "Named window in the workspace owner's timezone: `today`, `yesterday`, `last_week` (the 7 days before today) or `last_month` (the last 30 days including today). Ignored when dates are sent.",
                                        "enum": [
                                            "today",
                                            "yesterday",
                                            "last_week",
                                            "last_month"
                                        ],
                                        "default": "last_week",
                                        "example": "last_week"
                                    },
                                    "start_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "First day of the period, `YYYY-MM-DD`. Sent together with `end_date`; at most 366 days apart.",
                                        "example": "2026-10-01"
                                    },
                                    "end_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Last day of the period, `YYYY-MM-DD`, not before `start_date`.",
                                        "example": "2026-10-21"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7xQ2pL9k=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "period": {
                                            "type": "object",
                                            "description": "`{start, end, compare_start, compare_end}` as `YYYY-MM-DD`."
                                        },
                                        "labels": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Summary (no label_id): one entry per label of the owner, in the owner's label order, labels without posts included with zeros.",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain label id."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Label name."
                                                    },
                                                    "color": {
                                                        "type": "string",
                                                        "description": "Label colour as stored in the app."
                                                    },
                                                    "posts": {
                                                        "type": "integer",
                                                        "description": "Posts published in the period carrying the label."
                                                    },
                                                    "likes": {
                                                        "type": "integer",
                                                        "description": "Likes of those posts."
                                                    },
                                                    "comments": {
                                                        "type": "integer",
                                                        "description": "Comments."
                                                    },
                                                    "shares": {
                                                        "type": "integer",
                                                        "description": "Shares."
                                                    },
                                                    "clicks": {
                                                        "type": "integer",
                                                        "description": "Tracked link clicks."
                                                    },
                                                    "engagement": {
                                                        "type": "integer",
                                                        "description": "likes + comments + shares (clicks are not included)."
                                                    },
                                                    "best_post": {
                                                        "type": "object",
                                                        "description": "The label's most engaged post of the period in the shape of `posts[]` below, or `null` when the label had none."
                                                    },
                                                    "trend": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "array",
                                                            "items": [],
                                                            "description": "Eight buckets of equal length from the first to the last day of the period, oldest first, each `{posts, engagement}`."
                                                        }
                                                    }
                                                }
                                            }
                                        },
                                        "totals": {
                                            "type": "object",
                                            "properties": {
                                                "labels": {
                                                    "type": "integer",
                                                    "description": "Number of labels."
                                                },
                                                "posts_tagged": {
                                                    "type": "integer",
                                                    "description": "Sum of `labels[].posts`; a post with two labels counts twice."
                                                },
                                                "engagement": {
                                                    "type": "integer",
                                                    "description": "Sum of `labels[].engagement`."
                                                }
                                            }
                                        },
                                        "label": {
                                            "type": "object",
                                            "description": "List (label_id sent): `{id, name, color}` of the label."
                                        },
                                        "page": {
                                            "type": "integer",
                                            "description": "List: the page returned."
                                        },
                                        "per_page": {
                                            "type": "integer",
                                            "description": "List: page size used."
                                        },
                                        "total": {
                                            "type": "integer",
                                            "description": "List: published posts of the label in the period."
                                        },
                                        "posts": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "List: the page of posts, newest first.",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain id of the published post instance."
                                                    },
                                                    "post_id": {
                                                        "type": "integer",
                                                        "description": "Plain id of the post content it was published from."
                                                    },
                                                    "account": {
                                                        "type": "object",
                                                        "description": "`{id, name, network}` of the account it went out on (encrypted id)."
                                                    },
                                                    "posted_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "Publish time in the workspace owner's timezone."
                                                    },
                                                    "message": {
                                                        "type": "string",
                                                        "description": "Post text."
                                                    },
                                                    "url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Link in the post, if any."
                                                    },
                                                    "image_url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "First image, if any."
                                                    },
                                                    "video_url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Video, if any."
                                                    },
                                                    "likes": {
                                                        "type": "integer",
                                                        "description": "Likes the app has collected for the post."
                                                    },
                                                    "comments": {
                                                        "type": "integer",
                                                        "description": "Comments."
                                                    },
                                                    "shares": {
                                                        "type": "integer",
                                                        "description": "Shares (retweets, reposts)."
                                                    },
                                                    "clicks": {
                                                        "type": "integer",
                                                        "description": "Clicks on the post's tracked link."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "period": {
                                        "start": "2026-10-01",
                                        "end": "2026-10-21",
                                        "compare_start": "2026-09-10",
                                        "compare_end": "2026-09-30"
                                    },
                                    "labels": [
                                        {
                                            "id": 12,
                                            "name": "Product news",
                                            "color": "#2563eb",
                                            "posts": 6,
                                            "likes": 410,
                                            "comments": 38,
                                            "shares": 22,
                                            "clicks": 164,
                                            "engagement": 470,
                                            "best_post": {
                                                "id": 88213,
                                                "post_id": 51290,
                                                "account": {
                                                    "id": "nX2k9Qp7Lw==",
                                                    "name": "Acme Page",
                                                    "network": "facebook"
                                                },
                                                "posted_at": "2026-10-14 09:30:00",
                                                "message": "The new grinder is here.",
                                                "url": "https://acme.example/grinder",
                                                "image_url": "https://cdn.example.com/grinder.jpg",
                                                "video_url": "",
                                                "likes": 180,
                                                "comments": 21,
                                                "shares": 12,
                                                "clicks": 77
                                            },
                                            "trend": [
                                                {
                                                    "posts": 1,
                                                    "engagement": 60
                                                },
                                                {
                                                    "posts": 0,
                                                    "engagement": 0
                                                },
                                                {
                                                    "posts": 1,
                                                    "engagement": 45
                                                },
                                                {
                                                    "posts": 1,
                                                    "engagement": 52
                                                },
                                                {
                                                    "posts": 0,
                                                    "engagement": 0
                                                },
                                                {
                                                    "posts": 2,
                                                    "engagement": 213
                                                },
                                                {
                                                    "posts": 1,
                                                    "engagement": 100
                                                },
                                                {
                                                    "posts": 0,
                                                    "engagement": 0
                                                }
                                            ]
                                        },
                                        {
                                            "id": 13,
                                            "name": "Tips",
                                            "color": "#16a34a",
                                            "posts": 0,
                                            "likes": 0,
                                            "comments": 0,
                                            "shares": 0,
                                            "clicks": 0,
                                            "engagement": 0,
                                            "best_post": null,
                                            "trend": [
                                                {
                                                    "posts": 0,
                                                    "engagement": 0
                                                },
                                                {
                                                    "posts": 0,
                                                    "engagement": 0
                                                },
                                                {
                                                    "posts": 0,
                                                    "engagement": 0
                                                },
                                                {
                                                    "posts": 0,
                                                    "engagement": 0
                                                },
                                                {
                                                    "posts": 0,
                                                    "engagement": 0
                                                },
                                                {
                                                    "posts": 0,
                                                    "engagement": 0
                                                },
                                                {
                                                    "posts": 0,
                                                    "engagement": 0
                                                },
                                                {
                                                    "posts": 0,
                                                    "engagement": 0
                                                }
                                            ]
                                        }
                                    ],
                                    "totals": {
                                        "labels": 2,
                                        "posts_tagged": 6,
                                        "engagement": 470
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "period must be today, yesterday, last_week or last_month, or send start_date and end_date as YYYY-MM-DD at most 366 days apart. (Unknown period, a malformed date, end_date before start_date, or more than 366 days.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nLabel not found. (label_id was sent and is not a label of the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/report_ai_chat": {
            "post": {
                "tags": [
                    "Reports"
                ],
                "summary": "Ask the AI assistant about an account's report, or the workspace overview, for a period.",
                "description": "Feeds the report that `/api/report_account` would answer for the same `account_id` and period to the AI assistant as context and returns its answer to your `question`. Without `account_id` the context is the workspace overview across every account. The answer comes with a `chat_id` and the `history`; send both back with a new `question` to keep asking about the same report.\nA new chat spends one AI post credit of the workspace owner; a continued chat is checked against the owner's remaining credits by the app. Check the balance with `/api/ai_credits`.\n\nThe report is read live: Every call fetches the report from the network before asking the AI, so a question takes as long as `/api/report_account` plus the generation (often 15 to 60 seconds). Keep the period the same across the turns of one chat; the context is rebuilt from the period of each call.\n\nRoles in history: Turns carry `user` and `assistant`. This differs from `/api/generate_content_with_ai`, whose `chat_history` names the assistant `system`; the two histories are not interchangeable, but a `chat_id` from either endpoint continues the same chat.",
                "operationId": "report_ai_chat",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "question": {
                                        "type": "string",
                                        "description": "What to ask about the report, 1 to 5000 characters. On a follow-up call it is the next question in the same chat.",
                                        "example": "Make it shorter and add a question at the end"
                                    },
                                    "account_id": {
                                        "type": "string",
                                        "description": "Encrypted social account id from `/api/social_account_list`. Leave out to chat about the workspace overview.",
                                        "example": "nX2k9Qp7Lw=="
                                    },
                                    "chat_id": {
                                        "type": "string",
                                        "description": "Encrypted chat id returned by an earlier answer of this or another AI endpoint (the same value `/api/generate_content_with_ai` calls `ai_id`). Send it with `history` to refine that answer; leave it out to start fresh. Must be a chat of the workspace owner's account.",
                                        "example": "wX8yZ0aB2c=="
                                    },
                                    "history": {
                                        "type": "array",
                                        "items": [],
                                        "description": "The `history` array of the previous response, unchanged: up to 40 turns of `{role, content}` where `role` is `user` or `assistant` and `content` is 1 to 20000 characters. Required with `chat_id`. A JSON body array or a JSON string. Do not append your new `question` yourself.",
                                        "example": [
                                            {
                                                "role": "user",
                                                "content": "How did we do?"
                                            },
                                            {
                                                "role": "assistant",
                                                "content": "Engagement grew 12 percent against the previous period."
                                            }
                                        ]
                                    },
                                    "period": {
                                        "type": "string",
                                        "description": "Named window in the workspace owner's timezone: `today`, `yesterday`, `last_week` (the 7 days before today) or `last_month` (the last 30 days including today). Ignored when dates are sent.",
                                        "enum": [
                                            "today",
                                            "yesterday",
                                            "last_week",
                                            "last_month"
                                        ],
                                        "default": "last_week",
                                        "example": "last_week"
                                    },
                                    "start_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "First day of the period, `YYYY-MM-DD`. Sent together with `end_date`; at most 366 days apart.",
                                        "example": "2026-10-01"
                                    },
                                    "end_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Last day of the period, `YYYY-MM-DD`, not before `start_date`.",
                                        "example": "2026-10-21"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7xQ2pL9k=="
                                    }
                                },
                                "required": [
                                    "question"
                                ],
                                "example": {
                                    "question": "Make it shorter and add a question at the end"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "answer": {
                                            "type": "string",
                                            "description": "The generated text."
                                        },
                                        "chat_id": {
                                            "type": "string",
                                            "description": "Encrypted chat id. Pass it back with `history` to refine the answer."
                                        },
                                        "history": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "The turns so far: the history you sent, your question when you sent one, and the new answer last.",
                                                "properties": {
                                                    "role": {
                                                        "type": "string",
                                                        "description": "`user` or `assistant`."
                                                    },
                                                    "content": {
                                                        "type": "string",
                                                        "description": "Message text."
                                                    }
                                                }
                                            }
                                        },
                                        "credits_left": {
                                            "type": "integer",
                                            "description": "AI post credits the workspace owner has left after this call."
                                        },
                                        "context_used_percent": {
                                            "type": "integer",
                                            "description": "How much of the chat's context window is used, 0 to 100. Start a new chat when it nears 100."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "answer": "Engagement rose 9 percent on 18 posts, driven by the three photo posts of 14 October; comments grew fastest (+37 percent). Reach fell 5 percent, so the content is resonating with a slightly smaller audience.",
                                    "chat_id": "wX8yZ0aB2c==",
                                    "history": [
                                        {
                                            "role": "user",
                                            "content": "How did the page do compared with the previous three weeks?"
                                        },
                                        {
                                            "role": "assistant",
                                            "content": "Engagement rose 9 percent on 18 posts, driven by the three photo posts of 14 October; comments grew fastest (+37 percent). Reach fell 5 percent, so the content is resonating with a slightly smaller audience."
                                        }
                                    ],
                                    "credits_left": 38,
                                    "context_used_percent": 21
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "account_id is invalid. (account_id was sent but does not decrypt to one account id.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nquestion must be 1 to 5000 characters. (question is missing or blank where it is required, or longer than 5000 characters.)\n\nhistory must be a list of at most 40 turns. (history is not an array (or a JSON string of one), or has more than 40 entries.)\n\nEach history turn needs role user or assistant and content. (A history entry has another role, an empty content or one above 20000 characters.)\n\nhistory is required to continue a chat. (chat_id was sent without any history turn.)\n\nperiod must be today, yesterday, last_week or last_month, or send start_date and end_date as YYYY-MM-DD at most 366 days apart. (Unknown period, a malformed date, end_date before start_date, or more than 366 days.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The account belongs to another user or no longer exists for the workspace owner.)\n\nYour AI post credits are over. You can buy additional credits from the add-ons page right away. (The workspace owner has no AI post credit left. The text is the app's with its HTML link stripped; the wording varies with how the owner's plan was bought.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nchat_id is not one of this account's AI chats. (chat_id does not decrypt to an id, or the chat does not belong to the workspace owner.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and the account, although the owner's, is not attached to that workspace.)\n\nNo social account available. (The account is not visible to the report.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "This account needs to be reconnected in RecurPost before its report can be read. (The account's token has expired or the network refused it while reading the report.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "You have exceeded the limit for this chat. Please copy the latest response and start a new chat. (The conversation is longer than the model's context window; start a new chat without chat_id and history.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something went wrong (The report behind the chat could not be read; a message from the app replaces the default when it sent one.)\n\nThe AI could not answer. (The app did not answer with a generation. When the app sent its own error the status is the app's (400 when it answered 200 with an error text) and the message is the app's text, for example a refused prompt.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/custom_reports": {
            "post": {
                "tags": [
                    "Custom Reports"
                ],
                "summary": "List, read, create or update, duplicate and delete the workspace's custom report canvases.",
                "description": "One endpoint for the saved custom reports of the workspace: canvases of metric and note tiles over chosen accounts, with a default date mode, as built on the Custom Reports page. `action` picks the operation:\n- `list` (default): every report of the workspace, without tiles.\n- `get`: one report with its tiles.\n- `save`: create a report (no `report_id`) or change one (`report_id`). On a change, every field left out keeps its value; on a create, `name` is required and `date_mode` defaults to `Last Week`.\n- `duplicate`: copy a report and return the copy.\n- `delete`: remove a report; needs `confirm=true`.\n\nReports belong to the workspace and its owner; every member of the workspace reads and edits them. `report_id` is a plain integer.\n`data` reads the numbers behind the report's metric tiles, per account and combined, for the report's own date_mode or for `period` / `start_date` and `end_date`, with the comparison window the canvas uses (the same length of days just before). Note and custom tiles carry no numbers. `force_refresh=true` asks the networks again instead of the stored figures. X tiles may charge the caller's X wallet for data not yet stored, as in the app.\n\nMessages per action: `save` answers `Report created.` or `Report saved.`, `delete` answers `Report deleted.` with no `report`, the others `Success`.\n\nMetric keys: The API does not list the metric keys the canvas knows; they are the `metricId` values you see on reports built in the app (read one with `get`). An unknown key is accepted by this call and shows as an empty tile in the app.\n\nA save replaces the tile list: `tiles` and `accounts` are whole lists: send the complete list you want, not only the additions. Leave the field out to keep the current list.\n\nReading the numbers: Action `data` answers with `report_id`, `period`, `accounts` and `metrics` instead of `report`. Example: `{\"status\":200,\"message\":\"Success\",\"report_id\":5,\"period\":{\"start\":\"2026-09-01\",\"end\":\"2026-09-07\",\"compare_start\":\"2026-08-25\",\"compare_end\":\"2026-08-31\"},\"accounts\":[{\"account_id\":\"aB3dE5fG==\",\"name\":\"Page\",\"network\":\"facebook\",\"status\":\"active\"}],\"metrics\":{\"followers\":{\"per_account\":{\"aB3dE5fG==\":{\"value\":120,\"previous\":100,\"available\":true}},\"combined\":{\"value\":120,\"previous\":100}}}}`",
                "operationId": "custom_reports",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "What to do. Case does not matter.",
                                        "enum": [
                                            "list",
                                            "get",
                                            "data",
                                            "save",
                                            "duplicate",
                                            "delete"
                                        ],
                                        "default": "list",
                                        "example": "save"
                                    },
                                    "report_id": {
                                        "type": "integer",
                                        "description": "Plain report id from `list`. Required when action is `get`, `duplicate` or `delete`; on `save` it names the report to change, leave it out to create one.",
                                        "example": 5
                                    },
                                    "confirm": {
                                        "type": "boolean",
                                        "description": "Required when action is `delete`: send `true` to confirm the removal.",
                                        "example": true
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "Report name, 1 to 255 characters. Required when action is `save` and no `report_id` is sent (a create); optional on a change.",
                                        "example": "Weekly client overview"
                                    },
                                    "accounts": {
                                        "type": "array",
                                        "items": [],
                                        "description": "`save`: the social accounts the report covers, as encrypted ids from `/api/social_account_list` (a JSON array, a form array or a comma-separated string; up to 50). They must be the workspace owner's and, when `workspace_id` is sent, inside that workspace. Send an empty value to clear the list.",
                                        "example": [
                                            "nX2k9Qp7Lw==",
                                            "qR5tY8uI1o=="
                                        ]
                                    },
                                    "tiles": {
                                        "type": "array",
                                        "items": [],
                                        "description": "`save`: the tiles of the canvas, in display order, as a JSON array or a JSON string. Each tile is an object. A metric tile: `metricId` (a metric key of the app's custom report canvas, 1 to 60 lowercase letters, digits and hyphens, for example `followers` or `impressions`), `title` (up to 120 characters), `viz` (`number`, `line`, `area`, `bar`, `pie`, `list`, `table`, `funnel`, `gauge`, `heat` or `map`; default `number`), `size` (`quarter`, `third`, `half`, `threeq` or `full`; default `quarter`) and `compare` (blank, `previous` for the comparison window or `network`). A note tile: `metricId` `note`, `title`, `size` and `body` (up to 5000 characters). At most 60 tiles and 200000 bytes of JSON.",
                                        "example": [
                                            {
                                                "metricId": "followers",
                                                "title": "Followers",
                                                "viz": "number",
                                                "size": "quarter",
                                                "compare": "previous"
                                            },
                                            {
                                                "metricId": "impressions",
                                                "title": "Impressions by day",
                                                "viz": "line",
                                                "size": "half",
                                                "compare": ""
                                            },
                                            {
                                                "metricId": "note",
                                                "title": "Reading guide",
                                                "size": "full",
                                                "body": "Numbers compare with the previous period."
                                            }
                                        ]
                                    },
                                    "date_mode": {
                                        "type": "string",
                                        "description": "`save`: the period the report opens with: `Last Week`, `Last Month`, `Today`, `Yesterday` or a fixed range `YYYY-MM-DD|YYYY-MM-DD` (first day, a pipe, last day). Case matters.",
                                        "default": "Last Week",
                                        "example": "Last Month"
                                    },
                                    "template_key": {
                                        "type": "string",
                                        "description": "`save`: the template the canvas was started from, up to 50 letters, digits, `-` and `_`; blank for none. Kept for the app's own use.",
                                        "example": "overview"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7xQ2pL9k=="
                                    },
                                    "period": {
                                        "type": "string",
                                        "description": "With action data: `today`, `yesterday`, `last_week` or `last_month` in the owner's timezone. Defaults to the report's own date_mode.",
                                        "enum": [
                                            "today",
                                            "yesterday",
                                            "last_week",
                                            "last_month"
                                        ],
                                        "example": "last_week"
                                    },
                                    "start_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "With action data: first day, `YYYY-MM-DD`, with end_date; wins over period.",
                                        "example": "2026-10-01"
                                    },
                                    "end_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "With action data: last day, `YYYY-MM-DD`, at most a year after start_date.",
                                        "example": "2026-10-07"
                                    },
                                    "force_refresh": {
                                        "type": "boolean",
                                        "description": "With action data: ask the networks again instead of the stored figures.",
                                        "default": "false",
                                        "example": false
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "reports": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "`list`: the workspace's reports, in the shape of `report` without `tiles`."
                                            }
                                        },
                                        "report": {
                                            "type": "object",
                                            "description": "`get`, `save`, `duplicate`: the report (the copy on duplicate).",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "Plain report id."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Report name."
                                                },
                                                "template_key": {
                                                    "type": "string",
                                                    "description": "Template key or blank."
                                                },
                                                "date_mode": {
                                                    "type": "string",
                                                    "description": "Default period, as sent."
                                                },
                                                "accounts": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "array",
                                                        "items": [],
                                                        "description": "Encrypted ids of the covered social accounts."
                                                    }
                                                },
                                                "tiles_count": {
                                                    "type": "integer",
                                                    "description": "Number of tiles."
                                                },
                                                "tiles": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "array",
                                                        "items": [],
                                                        "description": "The tiles as stored, see `tiles`. Not in `list`."
                                                    }
                                                },
                                                "created_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "description": "Creation time, UTC."
                                                },
                                                "updated_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "description": "Last change, UTC."
                                                }
                                            }
                                        },
                                        "report_id": {
                                            "type": "integer",
                                            "description": "With action data: the report."
                                        },
                                        "period": {
                                            "type": "object",
                                            "properties": {
                                                "start": {
                                                    "type": "string",
                                                    "format": "date",
                                                    "description": "With action data: first day of the window read."
                                                },
                                                "end": {
                                                    "type": "string",
                                                    "format": "date",
                                                    "description": "With action data: last day."
                                                },
                                                "compare_start": {
                                                    "type": "string",
                                                    "format": "date",
                                                    "description": "With action data: first day of the comparison window."
                                                },
                                                "compare_end": {
                                                    "type": "string",
                                                    "format": "date",
                                                    "description": "With action data: last day of the comparison window."
                                                }
                                            }
                                        },
                                        "accounts": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "account_id": {
                                                        "type": "string",
                                                        "description": "With action data: encrypted account id."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Account name."
                                                    },
                                                    "network": {
                                                        "type": "string",
                                                        "description": "facebook, instagram, twitter, linkedin, pinterest, google_my_business, tiktok, youtube, threads or bluesky."
                                                    },
                                                    "status": {
                                                        "type": "string",
                                                        "description": "`active`, `paused` or `needs_reconnection`."
                                                    }
                                                }
                                            }
                                        },
                                        "metrics": {
                                            "type": "object",
                                            "properties": {
                                                "<metricId>": {
                                                    "type": "object",
                                                    "properties": {
                                                        "per_account": {
                                                            "type": "object",
                                                            "properties": {
                                                                "<account_id>": {
                                                                    "type": "object",
                                                                    "description": "With action data: the metric's figures for one account as the canvas reads them (value, previous and series fields depend on the metric; `available` is false when the network gave nothing)."
                                                                }
                                                            }
                                                        },
                                                        "combined": {
                                                            "type": "object",
                                                            "description": "With action data: the same figures added up across the report's accounts."
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Report created.",
                                    "report": {
                                        "id": 5,
                                        "name": "Weekly client overview",
                                        "template_key": "overview",
                                        "date_mode": "Last Month",
                                        "accounts": [
                                            "nX2k9Qp7Lw==",
                                            "qR5tY8uI1o=="
                                        ],
                                        "tiles_count": 3,
                                        "tiles": [
                                            {
                                                "metricId": "followers",
                                                "title": "Followers",
                                                "viz": "number",
                                                "size": "quarter",
                                                "compare": "previous"
                                            },
                                            {
                                                "metricId": "impressions",
                                                "title": "Impressions by day",
                                                "viz": "line",
                                                "size": "half",
                                                "compare": ""
                                            },
                                            {
                                                "metricId": "note",
                                                "title": "Reading guide",
                                                "size": "full",
                                                "body": "Numbers compare with the previous period."
                                            }
                                        ],
                                        "created_at": "2026-10-22 08:15:42",
                                        "updated_at": "2026-10-22 08:15:42"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "action must be list, get, data, save, duplicate or delete. (Another action was sent.)\n\nreport_id is required. (get, duplicate or delete without a report_id above 0.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nSend confirm=true to delete the report. (delete without confirm=true.)\n\nname must be 1 to 255 characters. (save: the name (sent, or the current one on a change) is blank or too long.)\n\ntemplate_key may hold letters, digits, - and _ only. (save: template_key has other characters or is longer than 50.)\n\ndate_mode must be Last Week, Last Month, Today, Yesterday or YYYY-MM-DD|YYYY-MM-DD. (save: date_mode is none of the named modes nor a pipe-separated date range.)\n\ndate_mode holds an invalid or reversed date range. (save: a fixed range with a date that does not exist or an end before the start.)\n\naccounts holds an invalid id. (save: one of the accounts does not decrypt to an id.)\n\nAt most 50 ids per call; 51 were sent. (save: more than 50 accounts; the second number is the count sent.)\n\ntiles must be a list of at most 60 tile objects. (save: tiles is not an array (or a JSON string of one), has more than 60 entries or more than 200000 bytes of JSON.)\n\ntiles[0]: metricId is required (a metric key, note or custom). (save: a tile without a usable metricId; the index names the tile. The other per-tile messages are: title may have at most 120 characters. / size must be quarter, third, half, threeq or full. / body may have at most 5000 characters. / viz must be one of number, line, area, bar, pie, list, table, funnel, gauge, heat, map. / compare must be blank, previous or network.)\n\nThis report has no metric tiles. (action data on a report of note or custom tiles only.)\n\nThis report has no accounts. (action data on a report with no accounts saved.)\n\nperiod must be today, yesterday, last_week or last_month, or start_date and end_date as YYYY-MM-DD, at most a year apart. (action data with a window the app does not take.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (save: an account belongs to another user or no longer exists for the workspace owner.)\n\nNo social account available. (action data when none of the report's accounts is readable any more.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nReport not found. (report_id is not a report of this workspace (get, save with report_id, duplicate, delete).)\n\nThis social account is not part of the selected workspace. (save: workspace_id was sent and an account is not attached to that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The reports could not be read. (list: the app did not answer the list; the status and message are the app's when it sent any.)\n\nThe report could not be deleted. (delete: the app refused; its status and message when it sent any.)\n\nThe report could not be duplicated. (duplicate: the app returned no new id; its status and message when it sent any.)\n\nThe report could not be saved. (save: the app returned no report id; its status and message when it sent any.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/custom_report_pdf": {
            "post": {
                "tags": [
                    "Custom Reports"
                ],
                "summary": "A custom report as a PDF for its own period or a given one, produced now or emailed.",
                "description": "Renders one custom report to a PDF. Without a period the report's own `date_mode` is used, as the app resolves it on the day of the call; `period` or `start_date` and `end_date` override it for this PDF only. Without `emails` the PDF is generated inside the request and its URL returned; with `emails` (up to 25 addresses) the app generates it in the background and mails the link.\n\nX tiles can charge the caller's X Wallet: A report that covers an X account renders its X tiles from stored data and, as in the app, fetches what is not stored yet, billed to the X Wallet of the API key's owner. Price and buy that data knowingly with `/api/report_x` before rendering, or keep X accounts out of reports you render by API.\n\nSlow without emails: Without `emails` every tile is computed and the PDF rendered inside the request, often 30 seconds or more. Prefer `emails` for large canvases, or raise your client timeout.\n\nMessage with emails: With `emails` the answer is `The report will be emailed to a@example.com, b@example.com.` and nothing is returned to poll; the recipients get the link when the PDF is ready.",
                "operationId": "custom_report_pdf",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "report_id": {
                                        "type": "integer",
                                        "description": "Plain report id from `/api/custom_reports`.",
                                        "example": 5
                                    },
                                    "emails": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Addresses to mail the PDF link to: one address, a comma-separated list, a JSON array or a form array; up to 25, lower-cased and de-duplicated. When sent, no `pdf_url` is returned.",
                                        "example": [
                                            "client@example.com"
                                        ]
                                    },
                                    "period": {
                                        "type": "string",
                                        "description": "Named window in the workspace owner's timezone: `today`, `yesterday`, `last_week` (the 7 days before today) or `last_month` (the last 30 days including today). Leave every period field out to use the report's own `date_mode`.",
                                        "enum": [
                                            "today",
                                            "yesterday",
                                            "last_week",
                                            "last_month"
                                        ],
                                        "example": "last_month"
                                    },
                                    "start_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "First day of the period, `YYYY-MM-DD`. Sent together with `end_date`; at most 366 days apart.",
                                        "example": "2026-10-01"
                                    },
                                    "end_date": {
                                        "type": "string",
                                        "format": "date",
                                        "description": "Last day of the period, `YYYY-MM-DD`, not before `start_date`.",
                                        "example": "2026-10-21"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "wS7xQ2pL9k=="
                                    }
                                },
                                "required": [
                                    "report_id"
                                ],
                                "example": {
                                    "report_id": 5
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "report_id": {
                                            "type": "integer",
                                            "description": "The report rendered."
                                        },
                                        "period": {
                                            "type": "object",
                                            "properties": {
                                                "start": {
                                                    "type": "string",
                                                    "format": "date",
                                                    "description": "First day used. Only present when a period was sent."
                                                },
                                                "end": {
                                                    "type": "string",
                                                    "format": "date",
                                                    "description": "Last day used. Only present when a period was sent."
                                                }
                                            }
                                        },
                                        "pdf_url": {
                                            "type": "string",
                                            "format": "uri",
                                            "description": "Download URL of the PDF. Only present without emails."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "report_id": 5,
                                    "period": {
                                        "start": "2026-10-01",
                                        "end": "2026-10-21"
                                    },
                                    "pdf_url": "https://cdn.example.com/reports/custom-weekly-client-overview-2026-10-22.pdf"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "report_id is required. (report_id is missing or not above 0.)\n\nemails holds an invalid address: ... (One of the addresses is not a valid email; the message ends with it.)\n\nAt most 25 recipients per call. (More than 25 distinct addresses.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nperiod must be today, yesterday, last_week or last_month, or start_date and end_date as YYYY-MM-DD, at most a year apart. (A period field was sent and is unknown, malformed, reversed or spans more than 366 days.)\n\nThe report PDF could not be produced. (The app answered without a PDF URL (or did not accept the email job). When the app reported a failure the status and message are the app's.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nReport not found. (report_id is not a report of this workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/ai_credits": {
            "post": {
                "tags": [
                    "AI"
                ],
                "summary": "Read the AI post and AI image credit counters of the workspace owner.",
                "description": "Returns, for AI posts and for AI images separately, the total allowance, how many have been used, how many are left and whether the allowance comes from a monthly add-on. Counters belong to the workspace owner, so every member of the workspace sees the same numbers.\n\nused can exceed total: `used` is a lifetime counter while `total` is the current allowance, so after a plan change `used` may be larger than `total`. Rely on `remaining` to decide whether a generation will go through.",
                "operationId": "ai_credits",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "ai_posts": {
                                            "type": "object",
                                            "properties": {
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total AI post generations the owner is allowed in the current period."
                                                },
                                                "used": {
                                                    "type": "integer",
                                                    "description": "Generations already spent."
                                                },
                                                "remaining": {
                                                    "type": "integer",
                                                    "description": "Generations left, never below 0."
                                                },
                                                "add_on": {
                                                    "type": "boolean",
                                                    "description": "`true` when the owner has an AI posts add-on."
                                                },
                                                "resets": {
                                                    "type": "string",
                                                    "description": "`monthly` with an add-on, otherwise `never` (the plan's one-off free allowance)."
                                                }
                                            }
                                        },
                                        "ai_images": {
                                            "type": "object",
                                            "properties": {
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Total AI image generations allowed."
                                                },
                                                "used": {
                                                    "type": "integer",
                                                    "description": "Image generations already spent."
                                                },
                                                "remaining": {
                                                    "type": "integer",
                                                    "description": "Image generations left, never below 0."
                                                },
                                                "add_on": {
                                                    "type": "boolean",
                                                    "description": "`true` when the owner has an AI images add-on."
                                                },
                                                "resets": {
                                                    "type": "string",
                                                    "description": "`monthly` or `never`, as for posts."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "ai_posts": {
                                        "total": 100,
                                        "used": 60,
                                        "remaining": 40,
                                        "add_on": true,
                                        "resets": "monthly"
                                    },
                                    "ai_images": {
                                        "total": 10,
                                        "used": 10,
                                        "remaining": 0,
                                        "add_on": false,
                                        "resets": "never"
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid workspace_id. (workspace_id does not decrypt to a workspace id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The AI credits could not be read. (One of the four counter reads failed in the app. The status and message are the app's own when it sent any.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/generate_content_with_ai": {
            "post": {
                "tags": [
                    "AI"
                ],
                "summary": "Generate post text from a prompt, with multi-turn follow-ups to refine it.",
                "description": "Sends your prompt to the AI assistant and returns the generated post text. The first call starts a chat and hands back an `ai_id`, a `chat_progress` marker and the `chat_history`. To refine the result, call again with a new `prompt_text` and pass all three back exactly as you received them; the assistant then answers in the context of the whole conversation.\nEvery successful call spends one AI post credit of the workspace owner. Check the balance with `/api/ai_credits`.\n\nSend the history back byte for byte: `chat_progress` encodes the length of `chat_history` as JSON. Store the array as returned and send it back unchanged, as a JSON body or a JSON string; re-ordering keys, trimming whitespace in messages or appending your new prompt to it makes the check fail with the `correct chat history` error.\n\nAssistant turns carry role system: The assistant's answers are stored with `role: system`, not `assistant`. Keep that value when you send the history back.\n\nLegacy endpoint: with body or Basic credentials errors arrive as HTTP 200 with the real status in the body field `status`. With a Bearer token it returns real HTTP status codes.",
                "operationId": "generate_content_with_ai",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "prompt_text": {
                                        "type": "string",
                                        "description": "What to write, up to 5000 characters. On a follow-up call this is the refinement instruction, for example `Make it shorter and add emojis`.",
                                        "example": "Write a social media post about our summer sale on cold brew"
                                    },
                                    "ai_id": {
                                        "type": "string",
                                        "description": "Encrypted chat id returned by the previous call. Send it to continue that chat; leave it out to start a new one. Requires `chat_progress` and `chat_history`.",
                                        "example": "wX8yZ0aB2c=="
                                    },
                                    "chat_progress": {
                                        "type": "string",
                                        "description": "Encrypted progress marker returned by the previous call. It is a check value on `chat_history`: the history you send must be the one the marker was issued for. Required with `ai_id`.",
                                        "example": "dE4fG6hI8j=="
                                    },
                                    "chat_history": {
                                        "type": "array",
                                        "items": [],
                                        "description": "The `chat_history` array of the previous response, unchanged: objects with `role` (`user` or `system`) and `content`. Required with `ai_id`. Do not append your new prompt yourself; send it in `prompt_text`.",
                                        "example": [
                                            {
                                                "role": "user",
                                                "content": "Write a social media post about our summer sale on cold brew"
                                            },
                                            {
                                                "role": "system",
                                                "content": "Beat the heat with 20% off every cold brew this week. Grab yours before the sun does."
                                            }
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "prompt_text"
                                ],
                                "example": {
                                    "prompt_text": "Write a social media post about our summer sale on cold brew"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "ai_content": {
                                            "type": "string",
                                            "description": "The generated post text."
                                        },
                                        "ai_id": {
                                            "type": "string",
                                            "description": "Encrypted chat id. Pass it back to continue the chat."
                                        },
                                        "chat_progress": {
                                            "type": "string",
                                            "description": "Encrypted progress marker for this state of the chat. Pass it back together with `chat_history`."
                                        },
                                        "chat_history": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Full conversation so far: the history you sent plus your prompt and the new answer.",
                                                "properties": {
                                                    "role": {
                                                        "type": "string",
                                                        "description": "`user` for your prompts, `system` for the assistant's answers."
                                                    },
                                                    "content": {
                                                        "type": "string",
                                                        "description": "Message text."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "ai_content": "Beat the heat with 20% off every cold brew this week. Grab yours before the sun does.",
                                    "ai_id": "wX8yZ0aB2c==",
                                    "chat_progress": "dE4fG6hI8j==",
                                    "chat_history": [
                                        {
                                            "role": "user",
                                            "content": "Write a social media post about our summer sale on cold brew"
                                        },
                                        {
                                            "role": "system",
                                            "content": "Beat the heat with 20% off every cold brew this week. Grab yours before the sun does."
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (prompt_text is missing or empty.)\n\nprompt_text may have at most 5000 characters. (prompt_text is longer than 5000 characters.)\n\nPlease share your chat progress to continue, or start a new chat to begin fresh. (ai_id was sent without chat_progress.)\n\nPlease share your chat history to continue, or start a new chat to begin fresh. (ai_id and chat_progress were sent without chat_history.)\n\nPlease share correct chat history to continue, or start a new chat to begin fresh. (chat_history does not match chat_progress, for example because it was edited or truncated.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nYour AI post credits are over. You can buy additional credits from the ... (A new chat is started and the owner has no AI post credit left. The text comes from the app and contains an HTML link to the add-ons page.)\n\nYou have exceeded the limit for this chat. Please copy the latest response and start a new chat. (The conversation is longer than the model's context window.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Your AI post credits are over. (A chat is continued and the owner has no AI post credit left.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nai_id not found. (ai_id does not belong to a chat of the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something wrong! please try again later. (The app answered without a chat id, usually a transient failure of the AI provider.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/generate_image_with_ai": {
            "post": {
                "tags": [
                    "AI"
                ],
                "summary": "Generate one image from a text description and get its URL.",
                "description": "Sends your description to the image model, stores the result in your RecurPost media storage and returns its URL. Use that URL as an image on `/api/post_content`, `/api/add_content_in_library` or any other endpoint that takes image URLs.\nEvery successful call spends one AI image credit of the workspace owner. Be descriptive: subject, setting, lighting and style give the best results.\n\nField name: The image URL is returned as `ai_image`. Older sample code that reads `image_url` from this response never worked.\n\nLegacy endpoint: with body or Basic credentials errors arrive as HTTP 200 with the real status in the body field `status`. With a Bearer token it returns real HTTP status codes.",
                "operationId": "generate_image_with_ai",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "prompt_text": {
                                        "type": "string",
                                        "description": "Description of the image, up to 5000 characters.",
                                        "example": "A professional photo of a steaming coffee cup on a rustic wooden table, morning sunlight, cozy cafe atmosphere"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "prompt_text"
                                ],
                                "example": {
                                    "prompt_text": "A professional photo of a steaming coffee cup on a rustic wooden table, morning sunlight, cozy cafe atmosphere"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "ai_image": {
                                            "type": "string",
                                            "format": "uri",
                                            "description": "URL of the generated image in your media storage."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "ai_image": "https://media.recurpost.com/ai/20261022/7f3a9c1e.png"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad Request Please try again later (prompt_text is missing or empty.)\n\nprompt_text may have at most 5000 characters. (prompt_text is longer than 5000 characters.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nYour AI image credits are over. You can purchase more from the ... (The owner has no AI image credit left. The text comes from the app and contains an HTML link to the billing page. Any other error the app reports, such as a refused prompt, is relayed the same way with status 400 and the app's text.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Something wrong! please try again later. (The app answered without an image, usually a transient failure of the AI provider.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/ai_hashtags": {
            "post": {
                "tags": [
                    "AI"
                ],
                "summary": "Suggest up to ten hashtags for a piece of text.",
                "description": "Asks the AI assistant for the most relevant hashtags for the given text and returns them as a list. The model is instructed to return at most ten lowercase tags without the `#` sign; add it yourself when a tag comes back without one. This endpoint spends no AI credit.",
                "operationId": "ai_hashtags",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "The post text to derive hashtags from, up to 5000 characters after trimming.",
                                        "example": "Fresh beans just landed. Come and taste the new Ethiopian single origin this weekend."
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "text"
                                ],
                                "example": {
                                    "text": "Fresh beans just landed. Come and taste the new Ethiopian single origin this weekend."
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "hashtags": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Suggested tags, trimmed, empty entries removed. Up to ten."
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "hashtags": [
                                        "coffee",
                                        "singleorigin",
                                        "ethiopiancoffee",
                                        "freshbeans",
                                        "specialtycoffee",
                                        "weekendvibes"
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "text is required. (text is missing or blank after trimming.)\n\ntext may have at most 5000 characters. (text is longer than 5000 characters.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The hashtags could not be generated. (The app did not answer with a hashtag list. When the model itself failed the status is 400 and the message is the app's, for example: There is an issue while generating hashtags. Please try again after sometime.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/ai_variations": {
            "post": {
                "tags": [
                    "AI"
                ],
                "summary": "Suggest text variations for a library post, from the AI or from a web page; nothing is saved.",
                "description": "Returns variation suggestions for one library post. With `source=ai` (the default) the assistant writes `count` short variations, each within the X character limit, in the tone set on the owner's account, from the `text` you give and the optional `url`. With `source=page` the app scrapes the given `url` and extracts candidate sentences from it.\nNothing is stored. Pick the suggestions you want to keep and save them with `/api/content_variation_add`.\n\nPartial results with count above 1: Each AI variation is a separate generation. When a later one fails, the ones already produced are returned with status 200 and the loop stops, so check the length of `variations` rather than assuming `count` entries. Identical suggestions are collapsed into one.\n\nSized for X: AI variations are written to fit the X character limit (280, or 257 when a `url` is given) so they can serve as alternate copies on any network. The library post's own text is not changed.",
                "operationId": "ai_variations",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "library_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library the post belongs to.",
                                        "example": "cD4eF6gH8i=="
                                    },
                                    "content_id": {
                                        "type": "string",
                                        "description": "Encrypted id of the library post the variations are for.",
                                        "example": "pQ7rS9tU1v=="
                                    },
                                    "source": {
                                        "type": "string",
                                        "description": "`ai` generates with the assistant, `page` extracts from the page at `url`. Case-insensitive.",
                                        "enum": [
                                            "ai",
                                            "page"
                                        ],
                                        "default": "ai",
                                        "example": "ai"
                                    },
                                    "text": {
                                        "type": "string",
                                        "description": "Post text to rewrite, up to 5000 characters. Used with `source=ai` only; send the post's current text or give at least a `url`.",
                                        "example": "Fresh beans just landed. Come and taste the new Ethiopian single origin this weekend."
                                    },
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "Public http or https address. Required with `source=page`; with `source=ai` it is given to the assistant as context and subtracted from the character budget as a link. Addresses that resolve to private or reserved IP ranges are refused.",
                                        "example": "https://acmecoffee.example/blog/ethiopian-single-origin"
                                    },
                                    "count": {
                                        "type": "integer",
                                        "description": "Number of variations to generate with `source=ai`, 1 to 3. Values outside the range are clamped. Ignored with `source=page`.",
                                        "default": "1",
                                        "example": 2
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "library_id",
                                    "content_id"
                                ],
                                "example": {
                                    "library_id": "cD4eF6gH8i==",
                                    "content_id": "pQ7rS9tU1v=="
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "variations": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Suggested variation texts, trimmed, duplicates and blanks removed. May hold fewer entries than `count`."
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "variations": [
                                        "New in: Ethiopian single origin, bright and floral. Taste it this weekend at Acme.",
                                        "Our new Ethiopian beans have landed. Swing by this weekend and try the first pour."
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "text may have at most 5000 characters. (text is longer than 5000 characters.)\n\nlibrary_id and content_id are required; source is ai or page. (library_id or content_id is missing or does not decrypt to one id, or source is another value.)\n\nurl must be a public http or https address. (url was sent but is not a valid http(s) URL or resolves to a private, loopback or reserved address.)\n\nsource page needs a url. (source is page and url is empty.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (The library or the library post does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and the library is not attached to that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "No variations could be read from that page. (source is page and the app could not scrape or parse the URL. The status and message are the app's own when it sent any.)\n\nThe variation could not be generated. (source is ai and the very first generation failed. The status and message are the app's own when it sent any, for example a 400 when the assistant refused.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/ai_templates": {
            "post": {
                "tags": [
                    "AI"
                ],
                "summary": "The app's AI post templates: list them, read a template's questions and formats, and generate a post from your answers.",
                "description": "The AI templates are guided prompts (a launch post, a testimonial, a how-to and so on): each asks a few questions and offers output formats. `action` picks the step:\n- `list` (default): the templates.\n- `questions`: the fields a template asks, for `template_id`.\n- `formats`: the output formats it offers, grouped by category.\n- `generate`: write the post from `answers` in the chosen `format`, with an optional `instruction`. The answer comes with a `chat_id` and `history`; send both back with a `question` (and the same template fields) to refine it.\n\nEvery new generation spends one AI post credit of the workspace owner. `template_id` is a plain integer.\n\nThe answer fields are read by label: The app matches your answers to the template's questions by their text, so send the `label` values from `questions` as the keys of `answers`.\n\nRefining keeps the template: On a refinement the app still receives `format` and `answers`, so send them again with the `question`, `chat_id` and `history`. A refinement with a `chat_id` continues the same chat; a call without one is a new generation and a new credit.",
                "operationId": "ai_templates",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "What to do. Case does not matter.",
                                        "enum": [
                                            "list",
                                            "questions",
                                            "formats",
                                            "generate"
                                        ],
                                        "default": "list",
                                        "example": "generate"
                                    },
                                    "template_id": {
                                        "type": "integer",
                                        "description": "Plain template id from `list`. Required when action is `questions`, `formats` or `generate`.",
                                        "example": 3
                                    },
                                    "format": {
                                        "type": "string",
                                        "description": "Required when action is `generate`: the `text` of one of the template's formats (from `formats`), up to 500 characters.",
                                        "example": "A short post with one call to action"
                                    },
                                    "answers": {
                                        "type": "object",
                                        "description": "Required when action is `generate`: your answers to the template's questions, as an object `{question label: answer}` or an array of `{question, answer}`; 1 to 30 entries, each question up to 500 and each answer up to 5000 characters. A JSON body value or a JSON string.",
                                        "example": {
                                            "Product or service": "The Acme hand grinder",
                                            "Who is it for": "Home baristas who travel"
                                        }
                                    },
                                    "instruction": {
                                        "type": "string",
                                        "description": "`generate`: extra guidance for the writer (length, audience, words to avoid), up to 2000 characters; longer text is cut.",
                                        "example": "Keep it under 60 words and end with a question"
                                    },
                                    "question": {
                                        "type": "string",
                                        "description": "`generate`: on a refinement, what to change in the answer (up to 5000 characters), sent with `chat_id` and `history`. Leave it out on the first generation.",
                                        "example": "Make it shorter and add a question at the end"
                                    },
                                    "chat_id": {
                                        "type": "string",
                                        "description": "Encrypted chat id returned by an earlier answer of this or another AI endpoint (the same value `/api/generate_content_with_ai` calls `ai_id`). Send it with `history` to refine that answer; leave it out to start fresh. Must be a chat of the workspace owner's account.",
                                        "example": "wX8yZ0aB2c=="
                                    },
                                    "history": {
                                        "type": "array",
                                        "items": [],
                                        "description": "The `history` array of the previous response, unchanged: up to 40 turns of `{role, content}` where `role` is `user` or `assistant` and `content` is 1 to 20000 characters. Required with `chat_id`. A JSON body array or a JSON string. Do not append your new `question` yourself.",
                                        "example": [
                                            {
                                                "role": "user",
                                                "content": "How did we do?"
                                            },
                                            {
                                                "role": "assistant",
                                                "content": "Engagement grew 12 percent against the previous period."
                                            }
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "templates": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "`list`: the templates.",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain template id."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Template name."
                                                    },
                                                    "description": {
                                                        "type": "string",
                                                        "description": "Short description."
                                                    }
                                                }
                                            }
                                        },
                                        "questions": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "`questions`: the fields the template asks, in display order.",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain question id."
                                                    },
                                                    "label": {
                                                        "type": "string",
                                                        "description": "The question; use it as the key in `answers`."
                                                    },
                                                    "placeholder": {
                                                        "type": "string",
                                                        "description": "Example answer the app shows."
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "description": "`text` or `textarea`."
                                                    },
                                                    "description": {
                                                        "type": "string",
                                                        "description": "Help text."
                                                    }
                                                }
                                            }
                                        },
                                        "categories": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "`formats`: format categories.",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain category id."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Category name."
                                                    },
                                                    "formats": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "array",
                                                            "items": [],
                                                            "description": "The formats of the category, each `{id, text}`; send `text` as `format`."
                                                        }
                                                    }
                                                }
                                            }
                                        },
                                        "answer": {
                                            "type": "string",
                                            "description": "The generated text."
                                        },
                                        "chat_id": {
                                            "type": "string",
                                            "description": "Encrypted chat id. Pass it back with `history` to refine the answer."
                                        },
                                        "history": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "The turns so far: the history you sent, your question when you sent one, and the new answer last.",
                                                "properties": {
                                                    "role": {
                                                        "type": "string",
                                                        "description": "`user` or `assistant`."
                                                    },
                                                    "content": {
                                                        "type": "string",
                                                        "description": "Message text."
                                                    }
                                                }
                                            }
                                        },
                                        "credits_left": {
                                            "type": "integer",
                                            "description": "AI post credits the workspace owner has left after this call."
                                        },
                                        "context_used_percent": {
                                            "type": "integer",
                                            "description": "How much of the chat's context window is used, 0 to 100. Start a new chat when it nears 100."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "answer": "Meet the Acme hand grinder: cafe-grade grounds from a tool that fits in a jacket pocket. Where will you brew first?",
                                    "chat_id": "kL3mN5oP7q==",
                                    "history": [
                                        {
                                            "role": "assistant",
                                            "content": "Meet the Acme hand grinder: cafe-grade grounds from a tool that fits in a jacket pocket. Where will you brew first?"
                                        }
                                    ],
                                    "credits_left": 39,
                                    "context_used_percent": 4
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "action must be list, questions, formats or generate. (Another action was sent.)\n\ntemplate_id is required. (questions, formats or generate without a template_id above 0.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nformat and answers ({question: answer}) are required. (generate: format is blank or over 500 characters, or answers is missing, empty, not an object or list, has more than 30 entries, a blank or over-long question or an over-long answer.)\n\nquestion must be 1 to 5000 characters. (question is missing or blank where it is required, or longer than 5000 characters.)\n\nhistory must be a list of at most 40 turns. (history is not an array (or a JSON string of one), or has more than 40 entries.)\n\nEach history turn needs role user or assistant and content. (A history entry has another role, an empty content or one above 20000 characters.)\n\nhistory is required to continue a chat. (chat_id was sent without any history turn.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Your AI post credits are over. You can buy additional credits from the add-ons page right away. (The workspace owner has no AI post credit left. The text is the app's with its HTML link stripped; the wording varies with how the owner's plan was bought.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nchat_id is not one of this account's AI chats. (chat_id does not decrypt to an id, or the chat does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "You have exceeded the limit for this chat. Please copy the latest response and start a new chat. (The conversation is longer than the model's context window; start a new chat without chat_id and history.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The templates could not be read. (list: the app did not answer; its status and message when it sent any.)\n\nThe questions could not be read. (questions: the app did not answer (an unknown template_id answers an empty list, not an error).)\n\nThe formats could not be read. (formats: the app did not answer.)\n\nThe AI could not answer. (The app did not answer with a generation. When the app sent its own error the status is the app's (400 when it answered 200 with an error text) and the message is the app's text, for example a refused prompt.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/ai_week_plan": {
            "post": {
                "tags": [
                    "AI"
                ],
                "summary": "Draft up to a week of posts from one brief, written for the chosen accounts; nothing is scheduled.",
                "description": "Asks the AI assistant for a set of post drafts across up to seven days, one to five posts per day, from an optional `idea`, in the given `tone` and `persona`, written for the networks of the `account_ids` you name. Every draft comes back as a base message, a per-network copy for each network in the plan and an image prompt you can pass to `/api/generate_image_with_ai`.\nNothing is scheduled or saved: post the drafts you keep with `/api/post_content` or add them to a library. One AI post credit of the workspace owner is spent per call.\n\nLong generation: The assistant writes every draft and its per-network copies in one go; seven days of five posts can take a minute or more. Keep your client timeout generous and do not retry while a call is running: each call spends a credit.\n\nDays are those the assistant returns: Drafts are grouped by the date the assistant put on them, normally the dates you asked for. A day the assistant left empty is absent from `days`.",
                "operationId": "ai_week_plan",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "days": {
                                        "type": "array",
                                        "items": [],
                                        "description": "1 to 7 entries of `{date, posts}`: `date` as `YYYY-MM-DD`, `posts` the number of drafts for that day, 1 to 5. A JSON body array or a JSON string.",
                                        "example": [
                                            {
                                                "date": "2026-11-02",
                                                "posts": 1
                                            },
                                            {
                                                "date": "2026-11-03",
                                                "posts": 2
                                            }
                                        ]
                                    },
                                    "account_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted social account ids from `/api/social_account_list` (a JSON array, a form array or a comma-separated string; up to 50). They set the networks the drafts are written for and must be the workspace owner's and, when `workspace_id` is sent, inside that workspace.",
                                        "example": [
                                            "nX2k9Qp7Lw==",
                                            "qR5tY8uI1o=="
                                        ]
                                    },
                                    "idea": {
                                        "type": "string",
                                        "description": "The brief: what the week is about, up to 5000 characters; longer text is cut.",
                                        "example": "Launch week of the Acme hand grinder: features, a how-to and a customer story"
                                    },
                                    "tone": {
                                        "type": "string",
                                        "description": "`neutral`, `cooperative`, `friendly`, `funny` or `sad` (the app's codes 1 to 5 are accepted too). Blank uses the writer's default rather than the owner's saved tone.",
                                        "enum": [
                                            "neutral",
                                            "cooperative",
                                            "friendly",
                                            "funny",
                                            "sad"
                                        ],
                                        "example": "friendly"
                                    },
                                    "persona": {
                                        "type": "string",
                                        "description": "Who is speaking (brand voice, audience), up to 2000 characters; longer text is cut.",
                                        "example": "A small specialty coffee roaster talking to home baristas"
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "days",
                                    "account_ids"
                                ],
                                "example": {
                                    "days": [
                                        {
                                            "date": "2026-11-02",
                                            "posts": 1
                                        },
                                        {
                                            "date": "2026-11-03",
                                            "posts": 2
                                        }
                                    ],
                                    "account_ids": [
                                        "nX2k9Qp7Lw==",
                                        "qR5tY8uI1o=="
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "days": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "The drafts grouped by day, in the order the assistant returned them.",
                                                "properties": {
                                                    "date": {
                                                        "type": "string",
                                                        "format": "date",
                                                        "description": "The day, `YYYY-MM-DD`."
                                                    },
                                                    "posts": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "array",
                                                            "items": [],
                                                            "description": "The day's drafts.",
                                                            "properties": {
                                                                "message": {
                                                                    "type": "string",
                                                                    "description": "The base post text."
                                                                },
                                                                "networks": {
                                                                    "type": "object",
                                                                    "description": "One key per network the draft was written for (`facebook`, `twitter`, `linkedin`, `instagram`, ...), each the copy adapted to that network."
                                                                },
                                                                "image_prompt": {
                                                                    "type": "string",
                                                                    "description": "A prompt for an image to go with the post, or blank."
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "days": [
                                        {
                                            "date": "2026-11-02",
                                            "posts": [
                                                {
                                                    "message": "Launch day. The Acme hand grinder is here: 40 click settings, steel burrs, fits in a jacket pocket.",
                                                    "networks": {
                                                        "facebook": "Launch day! The Acme hand grinder is here: 40 click settings, steel burrs and it fits in a jacket pocket. Tell us where you would take it.",
                                                        "twitter": "Launch day. 40 click settings, steel burrs, pocket sized. The Acme hand grinder is here."
                                                    },
                                                    "image_prompt": "A compact steel hand coffee grinder on a wooden table beside a travel mug, morning light"
                                                }
                                            ]
                                        },
                                        {
                                            "date": "2026-11-03",
                                            "posts": [
                                                {
                                                    "message": "How to dial in a pour-over on the Acme grinder in three steps.",
                                                    "networks": {
                                                        "facebook": "Three steps to a cleaner pour-over on the Acme grinder. Step one: start at click 22.",
                                                        "twitter": "Dial in a pour-over on the Acme grinder in three steps. Start at click 22."
                                                    },
                                                    "image_prompt": "Close-up of coffee grounds falling into a pour-over filter"
                                                },
                                                {
                                                    "message": "What our first testers said after a week with the grinder.",
                                                    "networks": {
                                                        "facebook": "A week in, our testers kept saying the same word: consistent. Here is what else they told us.",
                                                        "twitter": "One week, one word from our testers: consistent."
                                                    },
                                                    "image_prompt": "A smiling person holding a hand grinder in a bright kitchen"
                                                }
                                            ]
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "days (1 to 7 entries of {date, posts}) and account_ids are required. (days is missing, empty, not a list, longer than 7, or account_ids is missing or holds an id that does not decrypt.)\n\nEach day needs date as YYYY-MM-DD and posts from 1 to 5. (A day entry has a malformed date or a posts count outside 1 to 5.)\n\ntone must be neutral, cooperative, friendly, funny or sad. (tone is another word or code.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nAt most 50 ids per call; 51 were sent. (More than 50 account_ids; the second number is the count sent.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (An account belongs to another user or no longer exists for the workspace owner.)\n\nYour AI post credits are over. You can buy additional credits from the add-ons page right away. (The workspace owner has no AI post credit left. The text is the app's with its HTML link stripped; the wording varies with how the owner's plan was bought.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nThis social account is not part of the selected workspace. (workspace_id was sent and an account is not attached to that workspace.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "You have exceeded the limit for this chat. Please copy the latest response and start a new chat. (The conversation is longer than the model's context window; start a new chat without chat_id and history.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The week could not be generated. (The app did not answer with a generation. When the app sent its own error the status is the app's (400 when it answered 200 with an error text) and the message is the app's text, for example a refused prompt.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/ai_special_days": {
            "post": {
                "tags": [
                    "AI"
                ],
                "summary": "The calendar of occasions the app suggests posting about, and a post written for one of them on a network.",
                "description": "`action=list` (default) returns the app's calendar of special days and occasions from the current month on. `action=generate` writes a post about one occasion for one network, with an optional `instruction`. The answer comes with a `chat_id` and `history`; send both back with a `question` to refine it.\nEvery new generation spends one AI post credit of the workspace owner.\n\nlist has no year or day number: The calendar gives each occasion with its month only, as the app's picker does; the exact date is not stored. The list starts at the current month in the server's calendar.",
                "operationId": "ai_special_days",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "`list` or `generate`. Case does not matter.",
                                        "enum": [
                                            "list",
                                            "generate"
                                        ],
                                        "default": "list",
                                        "example": "generate"
                                    },
                                    "day": {
                                        "type": "string",
                                        "description": "Required when action is `generate`: the occasion's name, normally a `name` from `list` (any text up to 200 characters is accepted).",
                                        "example": "World Food Day"
                                    },
                                    "network": {
                                        "type": "string",
                                        "description": "Required when action is `generate`: the network to write for, as a key (`facebook`, `twitter`, `linkedin`, `instagram`, `pinterest`, `google_my_business`, `tiktok`, `youtube`, `threads`, `bluesky`) or a network name; up to 50 characters. A key is turned into the app's network name, any other value is handed to the writer as given.",
                                        "example": "instagram"
                                    },
                                    "instruction": {
                                        "type": "string",
                                        "description": "`generate`: extra guidance (mention a product, a length, a hashtag), up to 2000 characters; longer text is cut.",
                                        "example": "Mention our seasonal menu and keep it under 50 words"
                                    },
                                    "question": {
                                        "type": "string",
                                        "description": "`generate`: on a refinement, what to change in the answer (up to 5000 characters), sent with `chat_id` and `history`. Leave it out on the first generation.",
                                        "example": "Make it shorter and add a question at the end"
                                    },
                                    "chat_id": {
                                        "type": "string",
                                        "description": "Encrypted chat id returned by an earlier answer of this or another AI endpoint (the same value `/api/generate_content_with_ai` calls `ai_id`). Send it with `history` to refine that answer; leave it out to start fresh. Must be a chat of the workspace owner's account.",
                                        "example": "wX8yZ0aB2c=="
                                    },
                                    "history": {
                                        "type": "array",
                                        "items": [],
                                        "description": "The `history` array of the previous response, unchanged: up to 40 turns of `{role, content}` where `role` is `user` or `assistant` and `content` is 1 to 20000 characters. Required with `chat_id`. A JSON body array or a JSON string. Do not append your new `question` yourself.",
                                        "example": [
                                            {
                                                "role": "user",
                                                "content": "How did we do?"
                                            },
                                            {
                                                "role": "assistant",
                                                "content": "Engagement grew 12 percent against the previous period."
                                            }
                                        ]
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "days": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "`list`: the occasions from the current month to the end of the app's calendar.",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "Plain id of the entry."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "The occasion; send it as `day`."
                                                    },
                                                    "month": {
                                                        "type": "integer",
                                                        "description": "Month number, 1 to 12."
                                                    }
                                                }
                                            }
                                        },
                                        "answer": {
                                            "type": "string",
                                            "description": "The generated text."
                                        },
                                        "chat_id": {
                                            "type": "string",
                                            "description": "Encrypted chat id. Pass it back with `history` to refine the answer."
                                        },
                                        "history": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "The turns so far: the history you sent, your question when you sent one, and the new answer last.",
                                                "properties": {
                                                    "role": {
                                                        "type": "string",
                                                        "description": "`user` or `assistant`."
                                                    },
                                                    "content": {
                                                        "type": "string",
                                                        "description": "Message text."
                                                    }
                                                }
                                            }
                                        },
                                        "credits_left": {
                                            "type": "integer",
                                            "description": "AI post credits the workspace owner has left after this call."
                                        },
                                        "context_used_percent": {
                                            "type": "integer",
                                            "description": "How much of the chat's context window is used, 0 to 100. Start a new chat when it nears 100."
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Success",
                                    "answer": "Happy World Food Day! This week our seasonal menu celebrates the growers behind every cup: single-origin beans, roasted small, poured slow. Come taste the harvest.",
                                    "chat_id": "sD9fG1hJ3k==",
                                    "history": [
                                        {
                                            "role": "assistant",
                                            "content": "Happy World Food Day! This week our seasonal menu celebrates the growers behind every cup: single-origin beans, roasted small, poured slow. Come taste the harvest."
                                        }
                                    ],
                                    "credits_left": 37,
                                    "context_used_percent": 3
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "action must be list or generate. (Another action was sent.)\n\nday and network are required. (generate without day (or over 200 characters) or without network (or over 50 characters).)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nquestion must be 1 to 5000 characters. (question is missing or blank where it is required, or longer than 5000 characters.)\n\nhistory must be a list of at most 40 turns. (history is not an array (or a JSON string of one), or has more than 40 entries.)\n\nEach history turn needs role user or assistant and content. (A history entry has another role, an empty content or one above 20000 characters.)\n\nhistory is required to continue a chat. (chat_id was sent without any history turn.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Your AI post credits are over. You can buy additional credits from the add-ons page right away. (The workspace owner has no AI post credit left. The text is the app's with its HTML link stripped; the wording varies with how the owner's plan was bought.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nchat_id is not one of this account's AI chats. (chat_id does not decrypt to an id, or the chat does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "You have exceeded the limit for this chat. Please copy the latest response and start a new chat. (The conversation is longer than the model's context window; start a new chat without chat_id and history.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The special days could not be read. (list: the app did not answer; its status and message when it sent any.)\n\nThe AI could not answer. (The app did not answer with a generation. When the app sent its own error the status is the app's (400 when it answered 200 with an error text) and the message is the app's text, for example a refused prompt.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/ai_to_library": {
            "post": {
                "tags": [
                    "AI"
                ],
                "summary": "Copy an AI chat answer or a generated image set into one or more libraries as a new post.",
                "description": "Takes an AI result the workspace owner's account produced and adds it to libraries as a post: `chat_id` adds the latest text of that chat as a text post, `image_id` adds that generated image set as an image post. Exactly one of the two is sent, with `library_ids`. The post is added at the end of each library, as the in-app \"Add to library\" button does.\nIds are encrypted: `chat_id` is the value every AI endpoint returns (named `ai_id` by `/api/generate_content_with_ai`), `library_ids` come from `/api/library_list`.\n\nMessage: The success message is `Added to N library(ies).` where N is the number of libraries sent, whether or not every library got a new post; rely on `new_ids` for what was created.\n\nimage_id: `/api/generate_image_with_ai` returns the image URL only, not an `image_id`; the id belongs to the image sets kept in the app's AI history. To post an image you generated by API, pass its URL to `/api/add_content_in_library` or `/api/post_content` instead.",
                "operationId": "ai_to_library",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "library_ids": {
                                        "type": "array",
                                        "items": [],
                                        "description": "Encrypted library ids (a JSON array, a form array or a comma-separated string; up to 50). The libraries must be the workspace owner's and, when `workspace_id` is sent, attached to that workspace.",
                                        "example": [
                                            "cD4eF6gH8i=="
                                        ]
                                    },
                                    "chat_id": {
                                        "type": "string",
                                        "description": "Encrypted id of an AI chat (text answer). Required when `image_id` is not sent; never send both.",
                                        "example": "wX8yZ0aB2c=="
                                    },
                                    "image_id": {
                                        "type": "string",
                                        "description": "Encrypted id of a generated image set from the app's AI image history. Required when `chat_id` is not sent; never send both.",
                                        "example": "iM2nB4vC6x=="
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                },
                                "required": [
                                    "library_ids"
                                ],
                                "example": {
                                    "library_ids": [
                                        "cD4eF6gH8i=="
                                    ]
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "new_ids": {
                                            "type": "array",
                                            "items": {
                                                "type": "array",
                                                "items": [],
                                                "description": "Encrypted ids of the library posts created, one per library, usable as `content_id` on the library endpoints. Empty when the app added nothing new (for example the content was already there)."
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "Added to 2 library(ies).",
                                    "new_ids": [
                                        "pQ7rS9tU1v==",
                                        "zA3sX5dC7f=="
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Send chat_id or image_id, and library_ids. (Neither or both of chat_id and image_id were sent, one of them does not decrypt, or library_ids is missing or holds an id that does not decrypt.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\nAt most 50 ids per call; 51 were sent. (More than 50 library_ids; the second number is the count sent.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Sorry, there was an issue. Please try again later or contact support. (A library belongs to another user or no longer exists for the workspace owner.)\n\nYou have maximum allowed number of posts in your library. (The owner's plan limit on library posts is reached; any app message starting with You have maximum allowed is sent as 403.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)\n\nThis library is not part of the selected workspace. (workspace_id was sent and a library is not attached to that workspace.)\n\nThe AI result was not found among this account's. (The chat or image set does not belong to the workspace owner.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The content could not be added. (The app refused for another reason; its status and message when it sent any.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/ai_settings": {
            "post": {
                "tags": [
                    "AI"
                ],
                "summary": "Read or change the brand voice the AI writes with: tone, persona and inbox reply instructions.",
                "description": "The AI settings are the voice every generator reads: a `tone`, a `persona` (who is speaking, to whom) and `inbox_instructions` for AI-drafted inbox replies. They are kept on the workspace owner, so every workspace and member of that owner shares them. `action=get` (default) reads them; `action=set` changes them and is allowed to the workspace owner only. On `set`, every field left out keeps its value.\n\nMessages: `get` answers `Success`, `set` answers `AI settings saved.`; both return the settings as they now stand.\n\nWhere the voice is used: The saved tone and persona feed `/api/ai_variations`, the in-app composer and the inbox AI replies. `/api/ai_week_plan` takes its own `tone` and `persona` per call.",
                "operationId": "ai_settings",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "description": "`get` or `set`. Case does not matter.",
                                        "enum": [
                                            "get",
                                            "set"
                                        ],
                                        "default": "get",
                                        "example": "set"
                                    },
                                    "tone": {
                                        "type": "string",
                                        "description": "`set`: `neutral`, `cooperative`, `friendly`, `funny` or `sad` (the app's codes 1 to 5 are accepted too). Send an empty value to clear the tone.",
                                        "enum": [
                                            "neutral",
                                            "cooperative",
                                            "friendly",
                                            "funny",
                                            "sad",
                                            ""
                                        ],
                                        "example": "friendly"
                                    },
                                    "persona": {
                                        "type": "string",
                                        "description": "`set`: the brand persona the AI writes as, up to 2000 characters; an empty value clears it.",
                                        "example": "Acme Coffee, a small roaster. Warm, precise, never salesy. Talks to home baristas."
                                    },
                                    "inbox_instructions": {
                                        "type": "string",
                                        "description": "`set`: instructions for AI-drafted inbox replies, up to 2000 characters; an empty value clears them.",
                                        "example": "Reply in the customer's language, keep it under three sentences, never promise refunds."
                                    },
                                    "workspace_id": {
                                        "type": "string",
                                        "description": "Workspace to act in. Defaults to your default workspace. Get ids from `/api/workspace_list`.",
                                        "example": "nX2k9Qp7Lw=="
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "integer",
                                            "description": "200 on success."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "`Success`."
                                        },
                                        "settings": {
                                            "type": "object",
                                            "properties": {
                                                "tone": {
                                                    "type": "string",
                                                    "description": "`neutral`, `cooperative`, `friendly`, `funny`, `sad`, or blank when none is set."
                                                },
                                                "persona": {
                                                    "type": "string",
                                                    "description": "The persona text, or blank."
                                                },
                                                "inbox_instructions": {
                                                    "type": "string",
                                                    "description": "The inbox reply instructions, or blank."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": 200,
                                    "message": "AI settings saved.",
                                    "settings": {
                                        "tone": "friendly",
                                        "persona": "Acme Coffee, a small roaster. Warm, precise, never salesy. Talks to home baristas.",
                                        "inbox_instructions": "Reply in the customer's language, keep it under three sentences, never promise refunds."
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "action must be get or set. (Another action was sent.)\n\nInvalid workspace_id. (workspace_id does not decrypt to a workspace id.)\n\ntone must be neutral, cooperative, friendly, funny or sad. (set: tone is another word or code.)\n\npersona and inbox_instructions may have at most 2000 characters. (set: one of the two texts is longer than 2000 characters.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Missing or invalid credentials, or an expired access token (code token_expired).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Only the workspace owner can change the AI settings. (set by a member whose API key is not the workspace owner's.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Workspace not found or you do not have access to it. (The workspace does not exist or you are not its owner or an active member.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Per-minute rate limit reached; see Retry-After.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "The AI settings could not be read. (The app did not answer the current settings (read on both actions); its status and message when it sent any.)\n\nThe AI settings could not be saved. (set: the app refused the save; its status and message when it sent any.)",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "scheme": "bearer",
                "description": "Access token from /api/user_login, valid for one hour."
            },
            "basicAuth": {
                "type": "http",
                "scheme": "basic",
                "description": "base64(emailid:pass_key) on every call; no token needed."
            }
        },
        "schemas": {
            "Error": {
                "type": "object",
                "properties": {
                    "status": {
                        "type": "integer",
                        "description": "HTTP status of the error."
                    },
                    "error": {
                        "type": "string",
                        "description": "Human readable message."
                    },
                    "code": {
                        "type": "string",
                        "description": "Machine readable code on some errors (token_expired, token_invalid)."
                    }
                },
                "required": [
                    "status",
                    "error"
                ]
            }
        },
        "headers": {
            "X-RateLimit-Limit": {
                "description": "Calls allowed per minute on your plan.",
                "schema": {
                    "type": "integer"
                }
            },
            "X-RateLimit-Remaining": {
                "description": "Calls left in the current minute.",
                "schema": {
                    "type": "integer"
                }
            },
            "X-RateLimit-Reset": {
                "description": "Seconds until the minute window resets.",
                "schema": {
                    "type": "integer"
                }
            }
        }
    },
    "security": [
        {
            "bearerAuth": []
        },
        {
            "basicAuth": []
        }
    ]
}
