{
  "openapi": "3.1.0",
  "info": {
    "title": "Antwork API",
    "version": "v1",
    "description": "Draft, schedule and publish social posts on the accounts connected to your Antwork workspaces. Reference: https://antwork.io/docs/api"
  },
  "servers": [
    {
      "url": "https://antwork.io/api/v1"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "paths": {
    "/accounts": {
      "get": {
        "operationId": "listAccounts",
        "summary": "Connected accounts, their ids and their token health.",
        "description": "Scope: `read`.\n\nDocs: https://antwork.io/docs/api/list-accounts",
        "x-antwork-scope": "read",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/list-accounts"
        },
        "parameters": [
          {
            "name": "workspaceId",
            "in": "query",
            "required": false,
            "description": "Only accounts in this workspace.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "platform",
            "in": "query",
            "required": false,
            "description": "Only accounts on this platform.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Every connected account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountList"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/accounts/{accountId}": {
      "get": {
        "operationId": "getAccount",
        "summary": "One account, the settings a post to it takes, its Pinterest boards and its daily cap; on request its recent posts and best times.",
        "description": "Scope: `read`.\n\nDocs: https://antwork.io/docs/api/get-account",
        "x-antwork-scope": "read",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/get-account"
        },
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "description": "An account id from GET /accounts.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "include",
            "in": "query",
            "required": false,
            "description": "Comma-separated: `recentPosts` (the account’s posts, its voice; may read the platform, so it counts toward the platform-read limit) and `bestTimes`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountDetail"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_filter`.",
            "x-error-codes": [
              "invalid_filter"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `account_not_found`.",
            "x-error-codes": [
              "account_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `platform_read_rate_limited`, `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "platform_read_rate_limited",
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateAccount",
        "summary": "Set the account’s own posting rules: a daily maximum, a minimum gap between posts, and weekly posting slots.",
        "description": "Enforced like the platform caps: a post that breaks one is refused with `account_limit_reached` and `nextFreeAt`. `slots` are what `scheduledFor: \"next_slot\"` fills. The same settings as the web’s posting schedule and MCP `update_workspace(account_posting=…)`.\n\nScope: `write`.\n\nDocs: https://antwork.io/docs/api/get-account",
        "x-antwork-scope": "write",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/get-account"
        },
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "description": "An account id from GET /accounts.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AccountUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The account with its settings as saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountDetail"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_body`, `invalid_posting_settings`.",
            "x-error-codes": [
              "invalid_body",
              "invalid_posting_settings"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `role_forbidden`, `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "role_forbidden",
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `account_not_found`.",
            "x-error-codes": [
              "account_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/accounts/{accountId}/platform-posts:fetch": {
      "post": {
        "operationId": "fetchPlatformPosts",
        "summary": "The account’s recent posts read back from the platform itself, with metrics and permalinks.",
        "description": "MCP fetch_platform_posts for one account. A POST because it spends the account’s platform API quota; at most 10 per key per 10 minutes. A LinkedIn personal profile cannot be read back and answers `unsupported: true`. With `source` \"search\" (`query`) or \"account\" (`handle`) it reads other people’s public posts on this account’s network instead (X, YouTube, Bluesky, Mastodon; Instagram by creator only, on an account connected with the Facebook-based login; paid plans), ranked by `outlierScore`, and answers `DiscoveredPosts`.\n\nScope: `read`.\n\nDocs: https://antwork.io/docs/api/platform-posts",
        "x-antwork-scope": "read",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/platform-posts"
        },
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "description": "An account id from GET /accounts.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PlatformPostsFetch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The posts: `PlatformPosts`, or `DiscoveredPosts` with `source` \"search\" or \"account\".",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/PlatformPosts"
                    },
                    {
                      "$ref": "#/components/schemas/DiscoveredPosts"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_body`, `invalid_limit`.",
            "x-error-codes": [
              "invalid_body",
              "invalid_limit"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Refused. Codes: `discovery_requires_upgrade`.",
            "x-error-codes": [
              "discovery_requires_upgrade"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `account_not_found`, `creator_not_found`.",
            "x-error-codes": [
              "account_not_found",
              "creator_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict. Codes: `account_inactive`, `token_invalid`, `instagram_reconnect_for_discovery`.",
            "x-error-codes": [
              "account_inactive",
              "token_invalid",
              "instagram_reconnect_for_discovery"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `platform_read_rate_limited`, `discovery_x_weekly_limit`, `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "platform_read_rate_limited",
              "discovery_x_weekly_limit",
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Refused. Codes: `platform_error`.",
            "x-error-codes": [
              "platform_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/analytics/daily": {
      "get": {
        "operationId": "getDailyEngagement",
        "summary": "Engagement earned per day, as a table; or one post’s per-day history.",
        "description": "The per-day and follower tables MCP get_performance returns, from the same function. A null cell is a day not measured or a field the platform does not report; a 0 is a measured zero. `reachBasis` names what `impressions` counts, and different bases do not add, so the `all` row’s impressions is null on a mixed day. The daily rollup runs once a day.\n\nScope: `read`.\n\nDocs: https://antwork.io/docs/api/daily",
        "x-antwork-scope": "read",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/daily"
        },
        "parameters": [
          {
            "name": "workspaceId",
            "in": "query",
            "required": false,
            "description": "Required when the account has more than one workspace and no `postId` is given.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "Trailing window in days, today included, 1 to 365. Default 30; with `postId`, the whole history.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 365
            }
          },
          {
            "name": "postId",
            "in": "query",
            "required": false,
            "description": "One post’s history instead of the workspace’s.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The workspace table (with `followers`), or the post’s.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EngagementHistory"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `workspace_required`, `invalid_filter`.",
            "x-error-codes": [
              "workspace_required",
              "invalid_filter"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `workspace_not_found`, `post_not_found`.",
            "x-error-codes": [
              "workspace_not_found",
              "post_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/analytics/performance": {
      "get": {
        "operationId": "getPerformance",
        "summary": "Lifetime metrics per published post, and per-platform totals, over a window.",
        "description": "The same numbers as the analytics page and MCP get_performance. Metrics refresh every six hours. Bounded by the window and `limit`, not paged.\n\nScope: `read`.\n\nDocs: https://antwork.io/docs/api/performance",
        "x-antwork-scope": "read",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/performance"
        },
        "parameters": [
          {
            "name": "workspaceId",
            "in": "query",
            "required": false,
            "description": "Required when the account has more than one workspace.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "Window ending now, 1 to 730. Default 30.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 730,
              "default": 30
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "YYYY-MM-DD, with `to`; wins over `days`.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "YYYY-MM-DD, with `from`.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "platform",
            "in": "query",
            "required": false,
            "description": "Only this platform.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accountId",
            "in": "query",
            "required": false,
            "description": "Only this account; wins over `platform`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "compare",
            "in": "query",
            "required": false,
            "description": "`true` adds `previous`: the same totals over the preceding window.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "findings",
            "in": "query",
            "required": false,
            "description": "`true` adds `findings` (and `previous`): the period comparison, top and bottom posts, best windows, follower change and today's position against the daily cap.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows, 1 to 500. Default 200.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The report.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Performance"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `workspace_required`, `invalid_filter`, `invalid_limit`.",
            "x-error-codes": [
              "workspace_required",
              "invalid_filter",
              "invalid_limit"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `workspace_not_found`, `account_not_found`.",
            "x-error-codes": [
              "workspace_not_found",
              "account_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/campaigns/{campaignId}/publish": {
      "post": {
        "operationId": "publishCampaign",
        "summary": "Send every post of a campaign now; failed ones are retried.",
        "description": "Each post of the campaign on its own: one refused post does not hold the others back. At most 10 posts. Answers like POST /posts: a `post_result` per post, 202 when any was accepted, 400 with the first reason when none was. Poll each post with GET /posts/{postId}. TikTok posts take the user's choices in `tiktokSettings`, keyed by post id; one without them is rejected with `tiktok_choices_needed` and its `tiktokChoices`.\n\nScope: `publish`.\n\nDocs: https://antwork.io/docs/api/send-post",
        "x-antwork-scope": "publish",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/send-post"
        },
        "parameters": [
          {
            "name": "campaignId",
            "in": "path",
            "required": true,
            "description": "A campaign id, as POST /posts returns it.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "A retry with the same key and body replays the first answer instead of acting twice. See /docs/api/idempotency.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CampaignPublishBody"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "At least one post was queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostBatch"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_option`, `too_many_posts`.",
            "x-error-codes": [
              "invalid_option",
              "too_many_posts"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `campaign_not_found`.",
            "x-error-codes": [
              "campaign_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict. Codes: `idempotency_in_flight`.",
            "x-error-codes": [
              "idempotency_in_flight"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable. Codes: `idempotency_key_reused`.",
            "x-error-codes": [
              "idempotency_key_reused"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/campaigns/{campaignId}/schedule": {
      "post": {
        "operationId": "scheduleCampaign",
        "summary": "Schedule every post of a campaign at one time.",
        "description": "Each post of the campaign on its own: one refused post does not hold the others back. At most 10 posts. Answers like POST /posts: a `post_result` per post, 202 when any was accepted, 400 with the first reason when none was. Poll each post with GET /posts/{postId}. TikTok posts take the user's choices in `tiktokSettings`, keyed by post id; one without them is rejected with `tiktok_choices_needed` and its `tiktokChoices`.\n\nScope: `publish`.\n\nDocs: https://antwork.io/docs/api/send-post",
        "x-antwork-scope": "publish",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/send-post"
        },
        "parameters": [
          {
            "name": "campaignId",
            "in": "path",
            "required": true,
            "description": "A campaign id, as POST /posts returns it.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "A retry with the same key and body replays the first answer instead of acting twice. See /docs/api/idempotency.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CampaignScheduleBody"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "At least one post was scheduled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostBatch"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_body`, `invalid_option`, `invalid_scheduled_for`, `scheduled_for_in_past`, `scheduled_for_too_far`, `too_many_posts`.",
            "x-error-codes": [
              "invalid_body",
              "invalid_option",
              "invalid_scheduled_for",
              "scheduled_for_in_past",
              "scheduled_for_too_far",
              "too_many_posts"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `campaign_not_found`.",
            "x-error-codes": [
              "campaign_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict. Codes: `idempotency_in_flight`.",
            "x-error-codes": [
              "idempotency_in_flight"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable. Codes: `idempotency_key_reused`.",
            "x-error-codes": [
              "idempotency_key_reused"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/media": {
      "get": {
        "operationId": "listMedia",
        "summary": "The workspace media library, newest first.",
        "description": "Scope: `read`.\n\nDocs: https://antwork.io/docs/api/list-media",
        "x-antwork-scope": "read",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/list-media"
        },
        "parameters": [
          {
            "name": "workspaceId",
            "in": "query",
            "required": false,
            "description": "Required when the account has more than one workspace.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "`image`, `video` or `document` (`pdf` is accepted for `document`).",
            "schema": {
              "type": "string",
              "enum": [
                "image",
                "video",
                "document",
                "pdf"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size, 1 to 100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "`nextCursor` from the previous page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of media.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediaList"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `workspace_required`, `invalid_filter`, `invalid_limit`, `invalid_cursor`.",
            "x-error-codes": [
              "workspace_required",
              "invalid_filter",
              "invalid_limit",
              "invalid_cursor"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `workspace_not_found`.",
            "x-error-codes": [
              "workspace_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createMedia",
        "summary": "Add a file to the media library: from a public link, or a one-time address to upload one.",
        "description": "`upload: {filename, mimeType, size}` answers a one-time `uploadUrl` (10 minutes to start, one use) on the endpoint MCP `add_media(upload=…)` uses: one PUT of the bytes stores, registers and attaches the file. Otherwise the server fetches `url` (public http(s) hosts on the default port only; every redirect re-checked), reads the type from the bytes and stores it. PNG, JPEG, GIF, WebP, AVIF up to 10 MB; MP4, MOV, WebM and PDF up to 100 MB. `attachToPostIds` appends it to those posts. Each failure carries the code MCP `add_media(url=…)` gives it. At most 20 links that store nothing (a failed fetch, not a file) per key per 10 minutes; a link that stores a file does not count. A file that would take the workspace owner's media storage (across all their workspaces) past their plan's limit is refused before it is stored, `storage_limit_reached`; nothing already stored is touched.\n\nScope: `media`.\n\nDocs: https://antwork.io/docs/api/upload-media",
        "x-antwork-scope": "media",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/upload-media"
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "A retry with the same key and body replays the first answer instead of acting twice. See /docs/api/idempotency.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MediaCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "`url`: stored, and attached where asked. `upload`: the address to PUT the file to.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/MediaCreated"
                    },
                    {
                      "$ref": "#/components/schemas/MediaUpload"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_body`, `workspace_required`, `workspace_not_found`, `remote_http_error`, `not_a_file`, `unsupported_type`, `too_large`, `empty_file`, `blocked_url`, `fetch_timeout`, `fetch_failed`, `private_link`, `folder_link`.",
            "x-error-codes": [
              "invalid_body",
              "workspace_required",
              "workspace_not_found",
              "remote_http_error",
              "not_a_file",
              "unsupported_type",
              "too_large",
              "empty_file",
              "blocked_url",
              "fetch_timeout",
              "fetch_failed",
              "private_link",
              "folder_link"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Refused. Codes: `storage_limit_reached`.",
            "x-error-codes": [
              "storage_limit_reached"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `post_not_found`.",
            "x-error-codes": [
              "post_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict. Codes: `idempotency_in_flight`.",
            "x-error-codes": [
              "idempotency_in_flight"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable. Codes: `idempotency_key_reused`.",
            "x-error-codes": [
              "idempotency_key_reused"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `url_ingest_rate_limited`, `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "url_ingest_rate_limited",
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `storage_failed`, `internal_error`.",
            "x-error-codes": [
              "storage_failed",
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/media/{mediaId}": {
      "delete": {
        "operationId": "deleteMedia",
        "summary": "Remove a file from the media library. Refused while a post uses it.",
        "description": "Scope: `media`.\n\nDocs: https://antwork.io/docs/api/delete-media",
        "x-antwork-scope": "media",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/delete-media"
        },
        "parameters": [
          {
            "name": "mediaId",
            "in": "path",
            "required": true,
            "description": "A media id from GET /media.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MediaDeleted"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `media_not_found`.",
            "x-error-codes": [
              "media_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict. Codes: `media_in_use`.",
            "x-error-codes": [
              "media_in_use"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/platforms": {
      "get": {
        "operationId": "listPlatforms",
        "summary": "Character limits, media rules, daily caps and per-post settings of every platform.",
        "description": "Static, from the rules the publishers enforce. Holds nothing about the caller.\n\nAny valid key.\n\nDocs: https://antwork.io/docs/api/platforms",
        "x-antwork-scope": null,
        "externalDocs": {
          "url": "https://antwork.io/docs/api/platforms"
        },
        "responses": {
          "200": {
            "description": "Every platform.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformList"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `subscription_inactive`.",
            "x-error-codes": [
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/posts": {
      "get": {
        "operationId": "listPosts",
        "summary": "Every post on the account, newest first.",
        "description": "Unfiltered and campaign lists are ordered by createdAt, workspace and account lists by scheduledFor, `updatedSince` lists by updatedAt, newest first. Only filter combinations an index answers are served; any other is invalid_filter.\n\nScope: `read`.\n\nDocs: https://antwork.io/docs/api/list-posts",
        "x-antwork-scope": "read",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/list-posts"
        },
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Only posts in this status.",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "scheduled",
                "published",
                "failed",
                "pending_approval"
              ]
            }
          },
          {
            "name": "workspaceId",
            "in": "query",
            "required": false,
            "description": "Only this workspace's posts.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accountId",
            "in": "query",
            "required": false,
            "description": "Only this account's posts. Needs `status`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaignId",
            "in": "query",
            "required": false,
            "description": "Only this campaign's posts.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Scheduled at or after. Needs `workspaceId` or `accountId`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Scheduled at or before. Needs `workspaceId` or `accountId`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "description": "Changed at or after: the polling feed for triggers (`status=published&updatedSince=<last poll>`). Needs `status`; combines only with `workspaceId`. Dedupe on post id, since an edited post reappears.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size, 1 to 100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "`nextCursor` from the previous page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of posts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostList"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_status`, `invalid_limit`, `invalid_cursor`, `invalid_filter`.",
            "x-error-codes": [
              "invalid_status",
              "invalid_limit",
              "invalid_cursor",
              "invalid_filter"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `workspace_not_found`, `account_not_found`.",
            "x-error-codes": [
              "workspace_not_found",
              "account_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createPost",
        "summary": "Create posts, now, scheduled, or as drafts: one per account, or one per entry in `posts`.",
        "description": "Answers 202 with a per-target array: a target fails alone. Nothing publishes synchronously; poll GET /posts/{postId}. Send `accounts` (one copy fanned out, `options` keyed by platform) or `posts` (one entry per post, each with its own text, hashtags, userTags, media and options; an account named twice is two variants), never both. Every platform is accepted. A TikTok post takes the user's choices for it in its `posts[]` entry's `options` (the `TikTokSettings` shape); one to go out without them is rejected with `tiktok_choices_needed` and the `tiktokChoices` to ask.\n\nScope: `publish`. `write` is enough when `draft` is true.\n\nDocs: https://antwork.io/docs/api/create-post",
        "x-antwork-scope": "publish",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/create-post"
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "A retry with the same key and body replays the first answer instead of acting twice. See /docs/api/idempotency.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "accounts": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1,
                    "maxItems": 25,
                    "description": "Account ids from GET /accounts. Required unless `posts` is sent."
                  },
                  "text": {
                    "type": "string"
                  },
                  "texts": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Per-account copy, keyed by account id."
                  },
                  "media": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Library media ids (POST /media, GET /media) or Antwork-hosted media URLs."
                  },
                  "options": {
                    "type": "object",
                    "description": "Per-platform settings keyed by platform, as the composer offers them (`youtube.privacyStatus`, `pinterest.boardId`, ...). A `tiktok` key is refused: TikTok settings are chosen per post, in `posts[].options`."
                  },
                  "posts": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 25,
                    "description": "Instead of `accounts`, `text`, `texts`, `media` and `options`: one entry per post.",
                    "items": {
                      "$ref": "#/components/schemas/PostEntry"
                    }
                  },
                  "draft": {
                    "type": "boolean"
                  },
                  "scheduledFor": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Omit to publish now."
                  },
                  "workspaceId": {
                    "type": "string",
                    "description": "Required when the account has more than one workspace."
                  },
                  "campaignId": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "At least one target was accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostBatch"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `media_not_found`, `invalid_body`, `accounts_required`, `too_many_accounts`, `invalid_text`, `invalid_texts`, `invalid_hashtags`, `invalid_user_tags`, `invalid_media`, `media_not_hosted`, `media_not_in_library`, `invalid_scheduled_for`, `scheduled_for_in_past`, `scheduled_for_too_far`, `workspace_required`, `workspace_not_found`, `invalid_option`, `tiktok_settings_need_the_creator`, `account_unresolved`, `no_targets_accepted`.",
            "x-error-codes": [
              "media_not_found",
              "invalid_body",
              "accounts_required",
              "too_many_accounts",
              "invalid_text",
              "invalid_texts",
              "invalid_hashtags",
              "invalid_user_tags",
              "invalid_media",
              "media_not_hosted",
              "media_not_in_library",
              "invalid_scheduled_for",
              "scheduled_for_in_past",
              "scheduled_for_too_far",
              "workspace_required",
              "workspace_not_found",
              "invalid_option",
              "tiktok_settings_need_the_creator",
              "account_unresolved",
              "no_targets_accepted"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict. Codes: `idempotency_in_flight`.",
            "x-error-codes": [
              "idempotency_in_flight"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable. Codes: `idempotency_key_reused`.",
            "x-error-codes": [
              "idempotency_key_reused"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/posts/{postId}": {
      "delete": {
        "operationId": "deletePost",
        "summary": "Cancel or remove a post, and optionally the live one.",
        "description": "Scope: `write`.\n\nDocs: https://antwork.io/docs/api/delete-post",
        "x-antwork-scope": "write",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/delete-post"
        },
        "parameters": [
          {
            "name": "postId",
            "in": "path",
            "required": true,
            "description": "A post id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deleteFromPlatform",
            "in": "query",
            "required": false,
            "description": "`true` also deletes the published post on the platform.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostDeleted"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `post_not_found`.",
            "x-error-codes": [
              "post_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getPost",
        "summary": "One post, and what became of it.",
        "description": "Scope: `read`.\n\nDocs: https://antwork.io/docs/api/get-post",
        "x-antwork-scope": "read",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/get-post"
        },
        "parameters": [
          {
            "name": "postId",
            "in": "path",
            "required": true,
            "description": "A post id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The post, with links into the web composer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostDetail"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `post_not_found`.",
            "x-error-codes": [
              "post_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updatePost",
        "summary": "Change a draft, scheduled or failed post, or the text of a live one where the platform allows it.",
        "description": "A published post takes `text` alone, and changes the live post on LinkedIn, Facebook, Mastodon, Telegram, Discord, Google Business Profile, Pinterest and Slack (it needs `publish`); the other platforms answer `edit_not_supported_on_platform`. Text and hashtags are set (media and tags stay); `options` are merged one key at a time, `null` removes a key and `options: null` removes them all. `scheduledFor` on a scheduled post reschedules it; on a draft it only proposes a time. Nothing is written when an argument or a platform rule refuses; when the plan or the account has no room at the new time, the edit is saved, the old time kept, and the answer carries `post`.\n\nScope: `write`. Moving a scheduled post to a new time, or changing a published post, also needs `publish`.\n\nDocs: https://antwork.io/docs/api/update-post",
        "x-antwork-scope": "write",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/update-post"
        },
        "parameters": [
          {
            "name": "postId",
            "in": "path",
            "required": true,
            "description": "A post id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "A retry with the same key and body replays the first answer instead of acting twice. See /docs/api/idempotency.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The post as saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostDetail"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_body`, `invalid_text`, `invalid_hashtags`, `invalid_option`, `invalid_status`, `invalid_scheduled_for`, `scheduled_for_in_past`, `scheduled_for_too_far`, `account_unresolved`, `tiktok_settings_need_the_creator`, `unknown_pinterest_board`, `unknown_slack_channel`, `pinterest_board_create_failed`, `text_too_long`, `text_empty`, `media_required`, `unsupported_media`, `video_too_long`, `video_unsupported`, `media_too_large`, `image_aspect_ratio`, `too_many_mentions`, `too_many_cashtags`, `tiktok_privacy_required`, `pinterest_board_required`, `slack_channel_required`.",
            "x-error-codes": [
              "invalid_body",
              "invalid_text",
              "invalid_hashtags",
              "invalid_option",
              "invalid_status",
              "invalid_scheduled_for",
              "scheduled_for_in_past",
              "scheduled_for_too_far",
              "account_unresolved",
              "tiktok_settings_need_the_creator",
              "unknown_pinterest_board",
              "unknown_slack_channel",
              "pinterest_board_create_failed",
              "text_too_long",
              "text_empty",
              "media_required",
              "unsupported_media",
              "video_too_long",
              "video_unsupported",
              "media_too_large",
              "image_aspect_ratio",
              "too_many_mentions",
              "too_many_cashtags",
              "tiktok_privacy_required",
              "pinterest_board_required",
              "slack_channel_required"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `approval_required`, `x_link_requires_paid`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "approval_required",
              "x_link_requires_paid",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `post_not_found`.",
            "x-error-codes": [
              "post_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict. Codes: `post_already_published`, `post_not_editable`, `edit_not_supported_on_platform`, `live_post_not_found`, `account_unavailable`, `token_invalid`, `account_pending_payment`, `quota_exceeded`, `daily_cap_reached`, `schedule_queue_full`, `account_limit_reached`, `duplicate_post`, `posting_too_close`, `idempotency_in_flight`.",
            "x-error-codes": [
              "post_already_published",
              "post_not_editable",
              "edit_not_supported_on_platform",
              "live_post_not_found",
              "account_unavailable",
              "token_invalid",
              "account_pending_payment",
              "quota_exceeded",
              "daily_cap_reached",
              "schedule_queue_full",
              "account_limit_reached",
              "duplicate_post",
              "posting_too_close",
              "idempotency_in_flight"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable. Codes: `idempotency_key_reused`.",
            "x-error-codes": [
              "idempotency_key_reused"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `schedule_failed`, `internal_error`.",
            "x-error-codes": [
              "schedule_failed",
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Refused. Codes: `platform_error`.",
            "x-error-codes": [
              "platform_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/posts/{postId}/comments": {
      "get": {
        "operationId": "listPostComments",
        "summary": "Read the comments on a published post.",
        "description": "Read live from the network: newest first, each with its replies one level deep. X, Mastodon, Bluesky, LinkedIn company pages and YouTube today; Instagram, Facebook and Threads follow once Meta approves their comment permissions (until then 409 `comments_unsupported`; afterwards an account connected earlier answers 409 `reconnect_for_comments` until it is reconnected); TikTok, Pinterest, Discord, Telegram, Google Business Profile, Slack and LinkedIn personal profiles do not share comments with apps (409 `comments_unsupported`). X bills every reply read, so there a read returns at most 50, the first page is kept for 10 minutes (`cachedAt` when served from it; a reply through Antwork clears it), and the search reaches back 7 days: an older post answers `olderThanSearchWindow: true` and a `note`, because earlier replies are missing, not absent. `reply.allowed` says whether this network takes replies from Antwork.\n\nScope: `read`.\n\nDocs: https://antwork.io/docs/api/get-post",
        "x-antwork-scope": "read",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/get-post"
        },
        "parameters": [
          {
            "name": "postId",
            "in": "path",
            "required": true,
            "description": "A published post id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Comments to return, 1-50. Default 20.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "`nextCursor` from the previous page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The comments.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CommentList"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_limit`.",
            "x-error-codes": [
              "invalid_limit"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Refused. Codes: `comments_requires_upgrade`.",
            "x-error-codes": [
              "comments_requires_upgrade"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `post_not_found`.",
            "x-error-codes": [
              "post_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict. Codes: `not_published`, `comments_unsupported`, `reconnect_for_comments`, `account_inactive`.",
            "x-error-codes": [
              "not_published",
              "comments_unsupported",
              "reconnect_for_comments",
              "account_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Refused. Codes: `platform_error`.",
            "x-error-codes": [
              "platform_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "replyToPostComment",
        "summary": "Reply to a comment, or to the post.",
        "description": "Posts the reply at once, in public, as the account the post went out from. Without `commentId` it answers the post itself. The text is held to the network's character limit. A reply cannot be undone through the API.\n\nScope: `write`.\n\nDocs: https://antwork.io/docs/api/get-post",
        "x-antwork-scope": "write",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/get-post"
        },
        "parameters": [
          {
            "name": "postId",
            "in": "path",
            "required": true,
            "description": "A published post id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "A retry with the same key and body replays the first answer instead of acting twice. See /docs/api/idempotency.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommentReplyBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The reply, as the network stored it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CommentReplied"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_body`, `invalid_text`.",
            "x-error-codes": [
              "invalid_body",
              "invalid_text"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Refused. Codes: `comments_requires_upgrade`.",
            "x-error-codes": [
              "comments_requires_upgrade"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `post_not_found`.",
            "x-error-codes": [
              "post_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict. Codes: `not_published`, `comments_unsupported`, `reconnect_for_comments`, `account_inactive`, `idempotency_in_flight`.",
            "x-error-codes": [
              "not_published",
              "comments_unsupported",
              "reconnect_for_comments",
              "account_inactive",
              "idempotency_in_flight"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable. Codes: `idempotency_key_reused`.",
            "x-error-codes": [
              "idempotency_key_reused"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Refused. Codes: `platform_error`.",
            "x-error-codes": [
              "platform_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/posts/{postId}/media": {
      "put": {
        "operationId": "setPostMedia",
        "summary": "Set a post's media, in order.",
        "description": "The post's media becomes exactly `media`: reorder, trim, or `[]` to clear it. Each is a library media id or URL, and must be in this workspace's media library; one already on the post is always accepted. Sending the same list twice changes nothing, so no Idempotency-Key is read.\n\nScope: `media`.\n\nDocs: https://antwork.io/docs/api/update-post",
        "x-antwork-scope": "media",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/update-post"
        },
        "parameters": [
          {
            "name": "postId",
            "in": "path",
            "required": true,
            "description": "A post id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostMedia"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The post with its new media.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostDetail"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_body`, `invalid_media`, `media_not_found`, `media_not_in_library`.",
            "x-error-codes": [
              "invalid_body",
              "invalid_media",
              "media_not_found",
              "media_not_in_library"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `post_not_found`.",
            "x-error-codes": [
              "post_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict. Codes: `post_already_published`, `post_not_editable`.",
            "x-error-codes": [
              "post_already_published",
              "post_not_editable"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/posts/{postId}/publish": {
      "post": {
        "operationId": "publishPost",
        "summary": "Send a stored post now; a failed post is retried.",
        "description": "Commits the post with a delivery time of now and queues it. Answers 202 at once; poll GET /posts/{postId} for the outcome. In a workspace that requires approval the post is held as `status: \"pending_approval\"` instead, and goes out once a person approves it in the Antwork app. A failed post is requeued instead (`retried: true`). The checks and refusals are those of POST /posts. A TikTok post takes the user's choices for it in `tiktokSettings`; without them it is refused with `tiktok_choices_needed`, whose `tiktokChoices` lists what to ask.\n\nScope: `publish`.\n\nDocs: https://antwork.io/docs/api/send-post",
        "x-antwork-scope": "publish",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/send-post"
        },
        "parameters": [
          {
            "name": "postId",
            "in": "path",
            "required": true,
            "description": "A post id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "A retry with the same key and body replays the first answer instead of acting twice. See /docs/api/idempotency.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublishBody"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostSent"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `account_unresolved`, `text_too_long`, `text_empty`, `media_required`, `unsupported_media`, `video_too_long`, `video_unsupported`, `media_too_large`, `image_aspect_ratio`, `too_many_mentions`, `too_many_cashtags`, `invalid_option`, `tiktok_choices_needed`, `tiktok_creator_unavailable`, `tiktok_privacy_required`, `pinterest_board_required`, `slack_channel_required`.",
            "x-error-codes": [
              "account_unresolved",
              "text_too_long",
              "text_empty",
              "media_required",
              "unsupported_media",
              "video_too_long",
              "video_unsupported",
              "media_too_large",
              "image_aspect_ratio",
              "too_many_mentions",
              "too_many_cashtags",
              "invalid_option",
              "tiktok_choices_needed",
              "tiktok_creator_unavailable",
              "tiktok_privacy_required",
              "pinterest_board_required",
              "slack_channel_required"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `x_link_requires_paid`, `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "x_link_requires_paid",
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `post_not_found`.",
            "x-error-codes": [
              "post_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict. Codes: `post_already_published`, `token_invalid`, `account_pending_payment`, `quota_exceeded`, `daily_cap_reached`, `schedule_queue_full`, `account_limit_reached`, `duplicate_post`, `posting_too_close`, `idempotency_in_flight`.",
            "x-error-codes": [
              "post_already_published",
              "token_invalid",
              "account_pending_payment",
              "quota_exceeded",
              "daily_cap_reached",
              "schedule_queue_full",
              "account_limit_reached",
              "duplicate_post",
              "posting_too_close",
              "idempotency_in_flight"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable. Codes: `idempotency_key_reused`.",
            "x-error-codes": [
              "idempotency_key_reused"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/posts/{postId}/recurrence": {
      "delete": {
        "operationId": "deletePostRecurrence",
        "summary": "Stop a repeat or take the post out of the evergreen queue. Posts already made stay scheduled.",
        "description": "Scope: `publish`.\n\nDocs: https://antwork.io/docs/api/update-post",
        "x-antwork-scope": "publish",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/update-post"
        },
        "parameters": [
          {
            "name": "postId",
            "in": "path",
            "required": true,
            "description": "A post id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stopped.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecurrenceDeleted"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `recurrence_not_found`.",
            "x-error-codes": [
              "recurrence_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getPostRecurrence",
        "summary": "A post's repeat or evergreen setting.",
        "description": "Scope: `read`.\n\nDocs: https://antwork.io/docs/api/update-post",
        "x-antwork-scope": "read",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/update-post"
        },
        "parameters": [
          {
            "name": "postId",
            "in": "path",
            "required": true,
            "description": "A post id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The recurrence.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Recurrence"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `post_not_found`, `recurrence_not_found`.",
            "x-error-codes": [
              "post_not_found",
              "recurrence_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "setPostRecurrence",
        "summary": "Make a post repeat, or put it in its account's evergreen queue.",
        "description": "`repeat` ({every, unit: \"day\" | \"week\", until?, count?}) makes the post again on that rhythm, from its own time; only a scheduled or published post can repeat. `evergreen: true` re-sends it into the account's empty posting slots, least recently sent first, at `evergreenPerWeek` (default 3, shared by the account's evergreen posts). `variants` are alternate texts rotated per post. `repeat: null` or `evergreen: false` stops it. Each post made is a normal post with every check a scheduled one gets: one the plan, the account's cap or the duplicate rule refuses is skipped with its reason in `lastSkip`, and the rhythm carries on. Not on TikTok, which has the user confirm every post. Paid plans only.\n\nScope: `publish`.\n\nDocs: https://antwork.io/docs/api/update-post",
        "x-antwork-scope": "publish",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/update-post"
        },
        "parameters": [
          {
            "name": "postId",
            "in": "path",
            "required": true,
            "description": "A post id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "repeat": {
                    "oneOf": [
                      {
                        "$ref": "#/components/schemas/RepeatRule"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "evergreen": {
                    "type": "boolean"
                  },
                  "evergreenPerWeek": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 21
                  },
                  "variants": {
                    "type": "array",
                    "maxItems": 10,
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The recurrence as it is now, or `recurrence_deleted` when this stopped it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Recurrence"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_body`, `invalid_recurrence`.",
            "x-error-codes": [
              "invalid_body",
              "invalid_recurrence"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Refused. Codes: `recurring_requires_upgrade`.",
            "x-error-codes": [
              "recurring_requires_upgrade"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `post_not_found`, `recurrence_not_found`.",
            "x-error-codes": [
              "post_not_found",
              "recurrence_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict. Codes: `recurrence_unsupported_platform`, `post_not_bound`, `repeat_needs_scheduled_post`.",
            "x-error-codes": [
              "recurrence_unsupported_platform",
              "post_not_bound",
              "repeat_needs_scheduled_post"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/posts/{postId}/schedule": {
      "post": {
        "operationId": "schedulePost",
        "summary": "Schedule a stored post, or move a scheduled one.",
        "description": "The same checks as a publish, then the post is committed for `scheduledFor`. Answers 202; poll GET /posts/{postId}. In a workspace that requires approval the post is held as `status: \"pending_approval\"` until a person approves it in the Antwork app.\n\nScope: `publish`.\n\nDocs: https://antwork.io/docs/api/send-post",
        "x-antwork-scope": "publish",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/send-post"
        },
        "parameters": [
          {
            "name": "postId",
            "in": "path",
            "required": true,
            "description": "A post id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "A retry with the same key and body replays the first answer instead of acting twice. See /docs/api/idempotency.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScheduleBody"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Scheduled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostSent"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_body`, `invalid_scheduled_for`, `scheduled_for_in_past`, `scheduled_for_too_far`, `account_unresolved`, `text_too_long`, `text_empty`, `media_required`, `unsupported_media`, `video_too_long`, `video_unsupported`, `media_too_large`, `image_aspect_ratio`, `too_many_mentions`, `too_many_cashtags`, `invalid_option`, `tiktok_choices_needed`, `tiktok_creator_unavailable`, `tiktok_privacy_required`, `pinterest_board_required`, `slack_channel_required`.",
            "x-error-codes": [
              "invalid_body",
              "invalid_scheduled_for",
              "scheduled_for_in_past",
              "scheduled_for_too_far",
              "account_unresolved",
              "text_too_long",
              "text_empty",
              "media_required",
              "unsupported_media",
              "video_too_long",
              "video_unsupported",
              "media_too_large",
              "image_aspect_ratio",
              "too_many_mentions",
              "too_many_cashtags",
              "invalid_option",
              "tiktok_choices_needed",
              "tiktok_creator_unavailable",
              "tiktok_privacy_required",
              "pinterest_board_required",
              "slack_channel_required"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `x_link_requires_paid`, `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "x_link_requires_paid",
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `post_not_found`.",
            "x-error-codes": [
              "post_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict. Codes: `no_posting_slots`, `no_free_slot`, `post_already_published`, `token_invalid`, `account_pending_payment`, `quota_exceeded`, `daily_cap_reached`, `schedule_queue_full`, `account_limit_reached`, `duplicate_post`, `posting_too_close`, `idempotency_in_flight`.",
            "x-error-codes": [
              "no_posting_slots",
              "no_free_slot",
              "post_already_published",
              "token_invalid",
              "account_pending_payment",
              "quota_exceeded",
              "daily_cap_reached",
              "schedule_queue_full",
              "account_limit_reached",
              "duplicate_post",
              "posting_too_close",
              "idempotency_in_flight"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable. Codes: `idempotency_key_reused`.",
            "x-error-codes": [
              "idempotency_key_reused"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/posts/{postId}/unschedule": {
      "post": {
        "operationId": "unschedulePost",
        "summary": "Move a scheduled post back to draft; its queued publish is cancelled.",
        "description": "A post that is not scheduled is answered as it is, with `unscheduled: false`.\n\nScope: `write`.\n\nDocs: https://antwork.io/docs/api/send-post",
        "x-antwork-scope": "write",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/send-post"
        },
        "parameters": [
          {
            "name": "postId",
            "in": "path",
            "required": true,
            "description": "A post id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The post, now a draft.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostUnscheduled"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `post_not_found`.",
            "x-error-codes": [
              "post_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict. Codes: `post_already_published`.",
            "x-error-codes": [
              "post_already_published"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/recurrences": {
      "get": {
        "operationId": "listRecurrences",
        "summary": "A workspace's repeating and evergreen posts.",
        "description": "Scope: `read`.\n\nDocs: https://antwork.io/docs/api/update-post",
        "x-antwork-scope": "read",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/update-post"
        },
        "parameters": [
          {
            "name": "workspaceId",
            "in": "query",
            "required": false,
            "description": "Required when you belong to several workspaces.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Active first, then paused, then ended.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecurrenceList"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `workspace_required`.",
            "x-error-codes": [
              "workspace_required"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `workspace_not_found`.",
            "x-error-codes": [
              "workspace_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/recurrences/{recurrenceId}": {
      "patch": {
        "operationId": "updateRecurrence",
        "summary": "Pause or resume a repeat or evergreen post.",
        "description": "Scope: `publish`.\n\nDocs: https://antwork.io/docs/api/update-post",
        "x-antwork-scope": "publish",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/update-post"
        },
        "parameters": [
          {
            "name": "recurrenceId",
            "in": "path",
            "required": true,
            "description": "A recurrence id (its source post's id).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "status"
                ],
                "properties": {
                  "status": {
                    "enum": [
                      "active",
                      "paused"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The recurrence as it is now.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Recurrence"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_body`.",
            "x-error-codes": [
              "invalid_body"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Refused. Codes: `recurring_requires_upgrade`.",
            "x-error-codes": [
              "recurring_requires_upgrade"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `recurrence_not_found`.",
            "x-error-codes": [
              "recurrence_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/usage": {
      "get": {
        "operationId": "getUsage",
        "summary": "Your plan and quota position: posts this cycle and workspaces.",
        "description": "The numbers MCP list_workspaces reports, from the functions the enforcement uses. Daily per-account caps are on GET /accounts/{id}.\n\nScope: `read`.\n\nDocs: https://antwork.io/docs/api/usage",
        "x-antwork-scope": "read",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/usage"
        },
        "responses": {
          "200": {
            "description": "The usage.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "operationId": "listWebhooks",
        "summary": "A workspace's webhook endpoints.",
        "description": "Scope: `read`.\n\nDocs: https://antwork.io/docs/api/webhooks",
        "x-antwork-scope": "read",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/webhooks"
        },
        "parameters": [
          {
            "name": "workspaceId",
            "in": "query",
            "required": false,
            "description": "Required when you belong to several workspaces.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The endpoints, oldest first.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookList"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `workspace_required`.",
            "x-error-codes": [
              "workspace_required"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `role_forbidden`, `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "role_forbidden",
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `workspace_not_found`.",
            "x-error-codes": [
              "workspace_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createWebhook",
        "summary": "Register an https URL to receive signed events. Answers the signing secret once.",
        "description": "Deliveries are POSTs with Standard Webhooks headers (`webhook-id`, `webhook-timestamp`, `webhook-signature`). Failed deliveries are retried with backoff for about an hour; 20 undelivered events in a row disable the endpoint. At most 5 per workspace.\n\nScope: `write`.\n\nDocs: https://antwork.io/docs/api/webhooks",
        "x-antwork-scope": "write",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/webhooks"
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url",
                  "events"
                ],
                "properties": {
                  "workspaceId": {
                    "type": "string",
                    "description": "Required when you belong to several workspaces."
                  },
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "https, on the default port, resolving to a public address."
                  },
                  "events": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "enum": [
                        "post.scheduled",
                        "post.published",
                        "post.failed",
                        "account.needs_reconnect",
                        "account.disconnected"
                      ]
                    }
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 200
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Registered. `secret` is not shown again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookWithSecret"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_body`, `workspace_required`, `invalid_webhook_url`, `invalid_events`, `invalid_description`.",
            "x-error-codes": [
              "invalid_body",
              "workspace_required",
              "invalid_webhook_url",
              "invalid_events",
              "invalid_description"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Refused. Codes: `webhooks_requires_upgrade`.",
            "x-error-codes": [
              "webhooks_requires_upgrade"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `role_forbidden`, `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "role_forbidden",
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `workspace_not_found`.",
            "x-error-codes": [
              "workspace_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict. Codes: `webhook_limit`.",
            "x-error-codes": [
              "webhook_limit"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{webhookId}": {
      "delete": {
        "operationId": "deleteWebhook",
        "summary": "Remove a webhook endpoint. Deliveries already queued are dropped.",
        "description": "Scope: `write`.\n\nDocs: https://antwork.io/docs/api/webhooks",
        "x-antwork-scope": "write",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/webhooks"
        },
        "parameters": [
          {
            "name": "webhookId",
            "in": "path",
            "required": true,
            "description": "A webhook id from GET /webhooks.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeleted"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `webhook_not_found`.",
            "x-error-codes": [
              "webhook_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getWebhook",
        "summary": "One webhook endpoint, with its delivery health.",
        "description": "Scope: `read`.\n\nDocs: https://antwork.io/docs/api/webhooks",
        "x-antwork-scope": "read",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/webhooks"
        },
        "parameters": [
          {
            "name": "webhookId",
            "in": "path",
            "required": true,
            "description": "A webhook id from GET /webhooks.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `webhook_not_found`.",
            "x-error-codes": [
              "webhook_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateWebhook",
        "summary": "Change the URL, events or description, or switch the endpoint off and on.",
        "description": "Scope: `write`.\n\nDocs: https://antwork.io/docs/api/webhooks",
        "x-antwork-scope": "write",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/webhooks"
        },
        "parameters": [
          {
            "name": "webhookId",
            "in": "path",
            "required": true,
            "description": "A webhook id from GET /webhooks.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "events": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "type": "string"
                    }
                  },
                  "description": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 200
                  },
                  "status": {
                    "enum": [
                      "active",
                      "disabled"
                    ],
                    "description": "Back to `active` resets the failure count."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The endpoint as it is now.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_body`, `invalid_webhook_url`, `invalid_events`, `invalid_description`, `invalid_status`.",
            "x-error-codes": [
              "invalid_body",
              "invalid_webhook_url",
              "invalid_events",
              "invalid_description",
              "invalid_status"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `webhook_not_found`.",
            "x-error-codes": [
              "webhook_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{webhookId}/deliveries": {
      "get": {
        "operationId": "listWebhookDeliveries",
        "summary": "The last 50 delivery attempts, newest first, kept 30 days.",
        "description": "Scope: `read`.\n\nDocs: https://antwork.io/docs/api/webhooks",
        "x-antwork-scope": "read",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/webhooks"
        },
        "parameters": [
          {
            "name": "webhookId",
            "in": "path",
            "required": true,
            "description": "A webhook id from GET /webhooks.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One row per attempt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryList"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `webhook_not_found`.",
            "x-error-codes": [
              "webhook_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{webhookId}/rotate-secret": {
      "post": {
        "operationId": "rotateWebhookSecret",
        "summary": "A new signing secret, shown once. The old one stops signing at once.",
        "description": "Scope: `write`.\n\nDocs: https://antwork.io/docs/api/webhooks",
        "x-antwork-scope": "write",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/webhooks"
        },
        "parameters": [
          {
            "name": "webhookId",
            "in": "path",
            "required": true,
            "description": "A webhook id from GET /webhooks.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The endpoint and its new `secret`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookWithSecret"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `webhook_not_found`.",
            "x-error-codes": [
              "webhook_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{webhookId}/test": {
      "post": {
        "operationId": "testWebhook",
        "summary": "Send a signed `ping` event, even to a disabled endpoint.",
        "description": "Scope: `write`.\n\nDocs: https://antwork.io/docs/api/webhooks",
        "x-antwork-scope": "write",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/webhooks"
        },
        "parameters": [
          {
            "name": "webhookId",
            "in": "path",
            "required": true,
            "description": "A webhook id from GET /webhooks.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Queued. The outcome appears in the deliveries.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookTest"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Refused. Codes: `webhooks_requires_upgrade`.",
            "x-error-codes": [
              "webhooks_requires_upgrade"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `webhook_not_found`.",
            "x-error-codes": [
              "webhook_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/workspaces": {
      "get": {
        "operationId": "listWorkspaces",
        "summary": "Every workspace the key owner has, oldest first.",
        "description": "Scope: `read`.\n\nDocs: https://antwork.io/docs/api/list-workspaces",
        "x-antwork-scope": "read",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/list-workspaces"
        },
        "responses": {
          "200": {
            "description": "Every usable workspace; not paged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceList"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createWorkspace",
        "summary": "Create a workspace.",
        "description": "Scope: `write`.\n\nDocs: https://antwork.io/docs/api/create-workspace",
        "x-antwork-scope": "write",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/create-workspace"
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "A retry with the same key and body replays the first answer instead of acting twice. See /docs/api/idempotency.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "additionalProperties": false,
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60
                  },
                  "website": {
                    "type": "string",
                    "description": "https URL; a bare host gets https://."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Workspace"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_body`, `invalid_name`, `invalid_website`.",
            "x-error-codes": [
              "invalid_body",
              "invalid_name",
              "invalid_website"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Refused. Codes: `workspace_limit`.",
            "x-error-codes": [
              "workspace_limit"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `account_under_review`, `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "account_under_review",
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict. Codes: `idempotency_in_flight`.",
            "x-error-codes": [
              "idempotency_in_flight"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable. Codes: `idempotency_key_reused`.",
            "x-error-codes": [
              "idempotency_key_reused"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}": {
      "patch": {
        "operationId": "updateWorkspace",
        "summary": "Change a workspace's name, website, logo or settings.",
        "description": "Only the fields sent change; \"\" or null clears website or logoUrl, \"\" clears timezone. Bumps brandVersion.\n\nScope: `write`.\n\nDocs: https://antwork.io/docs/api/update-workspace",
        "x-antwork-scope": "write",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/update-workspace"
        },
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "A workspace id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "minProperties": 1,
                "additionalProperties": false,
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60
                  },
                  "website": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "https URL, or \"\" / null to clear."
                  },
                  "logoUrl": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "https URL, or \"\" / null to clear."
                  },
                  "timezone": {
                    "type": "string",
                    "description": "IANA timezone for scheduling, e.g. \"Europe/Madrid\"; \"\" clears it."
                  },
                  "preferredTimes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "pattern": "^\\d{2}:\\d{2}$"
                    },
                    "description": "Preferred posting times as HH:MM."
                  },
                  "tagOutboundLinks": {
                    "type": "boolean",
                    "description": "Append UTM parameters to links on the workspace's own website when a post publishes."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The workspace as saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Workspace"
                }
              }
            }
          },
          "400": {
            "description": "The request was refused. Codes: `invalid_body`, `invalid_name`, `invalid_website`, `invalid_logo_url`, `invalid_timezone`, `invalid_preferred_times`, `invalid_tag_outbound_links`.",
            "x-error-codes": [
              "invalid_body",
              "invalid_name",
              "invalid_website",
              "invalid_logo_url",
              "invalid_timezone",
              "invalid_preferred_times",
              "invalid_tag_outbound_links"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `role_forbidden`, `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "role_forbidden",
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `workspace_not_found`.",
            "x-error-codes": [
              "workspace_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/connect-urls": {
      "get": {
        "operationId": "getConnectUrls",
        "summary": "A link per platform that connects or reconnects an account to this workspace.",
        "description": "OAuth happens in the browser of whoever opens the link. Links work for 15 minutes (`expiresAt`).\n\nScope: `read`.\n\nDocs: https://antwork.io/docs/api/connect-urls",
        "x-antwork-scope": "read",
        "externalDocs": {
          "url": "https://antwork.io/docs/api/connect-urls"
        },
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "A workspace id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The links.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectUrls"
                }
              }
            }
          },
          "401": {
            "description": "No usable API key. Codes: `api_key_missing`, `api_key_malformed`, `api_key_unknown`, `api_key_revoked`.",
            "x-error-codes": [
              "api_key_missing",
              "api_key_malformed",
              "api_key_unknown",
              "api_key_revoked"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key cannot do this. Codes: `insufficient_scope`, `subscription_inactive`.",
            "x-error-codes": [
              "insufficient_scope",
              "subscription_inactive"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found on this account. Codes: `workspace_not_found`.",
            "x-error-codes": [
              "workspace_not_found"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. See the X-RateLimit-* and Retry-After headers. Codes: `rate_limit_burst`, `rate_limit_daily`.",
            "x-error-codes": [
              "rate_limit_burst",
              "rate_limit_daily"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Something went wrong on our end. Codes: `internal_error`.",
            "x-error-codes": [
              "internal_error"
            ],
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "`Authorization: Bearer ak_...`. See /docs/api/keys."
      }
    },
    "schemas": {
      "Account": {
        "type": "object",
        "required": [
          "object",
          "id",
          "workspaceId",
          "platform",
          "name",
          "active",
          "tokenHealth"
        ],
        "properties": {
          "object": {
            "const": "account"
          },
          "id": {
            "type": "string"
          },
          "workspaceId": {
            "type": "string"
          },
          "platform": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "handle": {
            "type": [
              "string",
              "null"
            ]
          },
          "accountType": {
            "type": [
              "string",
              "null"
            ]
          },
          "active": {
            "type": "boolean"
          },
          "tokenHealth": {
            "type": "string"
          },
          "connectedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "platformHold": {
            "type": "object",
            "description": "Present while the platform holds a working connection: `instagram_checkpoint` (the owner clears a notice in Instagram) or `instagram_action_blocked` (posts held until `until`). Reconnecting does not lift it; `advice` says what does.",
            "required": [
              "kind",
              "since",
              "advice"
            ],
            "properties": {
              "kind": {
                "enum": [
                  "instagram_checkpoint",
                  "instagram_action_blocked"
                ]
              },
              "since": {
                "type": "string",
                "format": "date-time"
              },
              "until": {
                "type": "string",
                "format": "date-time"
              },
              "advice": {
                "type": "string"
              }
            }
          }
        }
      },
      "AccountDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Account"
          },
          {
            "type": "object",
            "required": [
              "settings"
            ],
            "properties": {
              "settings": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SettingField"
                }
              },
              "boards": {
                "type": [
                  "array",
                  "null"
                ],
                "description": "Pinterest only. Null when Pinterest refused the lookup.",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    }
                  }
                }
              },
              "boardsError": {
                "type": "string"
              },
              "slackChannels": {
                "type": [
                  "array",
                  "null"
                ],
                "description": "Slack only: the channels the person who connected the account is a member of, as `{id, name}` (`#name`). Null when Slack could not be asked.",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    }
                  }
                }
              },
              "defaultSlackChannel": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "Slack only: where a post with no `channel` goes, the channel of the last published post. Null until a post names one; a Slack post with neither is refused (`slack_channel_required`).",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              },
              "reconnect": {
                "type": "boolean"
              },
              "dailyPostCap": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "Posts this account may publish per rolling 24 hours on the owner's plan, and what is left. `remaining` subtracts both the posts published in the last 24 hours and those scheduled in the next 24, as the cap check does. `publishedLast24h` and `remaining` are absent when the count could not be read.",
                "properties": {
                  "limit": {
                    "type": "integer"
                  },
                  "windowHours": {
                    "const": 24
                  },
                  "tier": {
                    "type": "string",
                    "enum": [
                      "free",
                      "paid"
                    ]
                  },
                  "publishedLast24h": {
                    "type": "integer"
                  },
                  "scheduledNext24h": {
                    "type": "integer"
                  },
                  "remaining": {
                    "type": "integer"
                  },
                  "platformLimit": {
                    "type": "integer",
                    "description": "The platform's maximum on the plan, when the owner set a lower `accountLimit`."
                  },
                  "accountLimit": {
                    "type": "integer",
                    "description": "The owner’s own daily maximum (`posting.maxPostsPerDay`); then it is `limit`."
                  },
                  "minGapMinutes": {
                    "type": "integer",
                    "description": "The owner’s minimum gap between this account’s posts."
                  }
                }
              },
              "posting": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/PostingSettings"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "recentPosts": {
                "type": "array",
                "description": "With `include=recentPosts`: up to 15 of the account’s posts, its voice, text cut at 600 characters.",
                "items": {
                  "type": "object",
                  "properties": {
                    "text": {
                      "type": "string"
                    },
                    "publishedAt": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "metrics": {
                      "type": "object"
                    }
                  }
                }
              },
              "bestTimes": {
                "type": "object",
                "description": "With `include=bestTimes`: the suggested posting times the composer shows."
              }
            }
          }
        ]
      },
      "AccountList": {
        "type": "object",
        "required": [
          "object",
          "accounts"
        ],
        "properties": {
          "object": {
            "const": "list"
          },
          "accounts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Account"
            }
          }
        }
      },
      "AccountUpdate": {
        "type": "object",
        "required": [
          "posting"
        ],
        "properties": {
          "posting": {
            "type": "object",
            "description": "Fields to change; `null` removes one. `slots: []` or `null` removes the slots.",
            "properties": {
              "maxPostsPerDay": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "minGapMinutes": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "timezone": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "slots": {
                "type": [
                  "array",
                  "null"
                ],
                "items": {
                  "type": "object",
                  "properties": {
                    "day": {
                      "type": "integer"
                    },
                    "time": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "CampaignPublishBody": {
        "type": "object",
        "properties": {
          "tiktokSettings": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/TikTokSettings"
            },
            "description": "Each TikTok post's settings, keyed by post id."
          }
        }
      },
      "CampaignScheduleBody": {
        "type": "object",
        "required": [
          "scheduledFor"
        ],
        "properties": {
          "scheduledFor": {
            "type": "string",
            "format": "date-time",
            "description": "When to publish: in the future (Free: at most 30 days ahead; paid plans: any time)."
          },
          "tiktokSettings": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/TikTokSettings"
            },
            "description": "Each TikTok post's settings, keyed by post id."
          }
        }
      },
      "Comment": {
        "type": "object",
        "required": [
          "id",
          "parentId",
          "author",
          "text",
          "createdAt",
          "canReply"
        ],
        "description": "A comment on a published post, as the network returned it (`src/lib/comments/types.ts`). Nothing is stored.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The network's id; pass it back as `commentId` to reply."
          },
          "parentId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The comment this one answers; null for a comment on the post."
          },
          "author": {
            "type": "object",
            "required": [
              "name",
              "handle",
              "avatarUrl"
            ],
            "properties": {
              "name": {
                "type": "string",
                "description": "Empty where the network does not share it (LinkedIn members)."
              },
              "handle": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "avatarUrl": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "text": {
            "type": "string"
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "likeCount": {
            "type": "integer"
          },
          "replies": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Comment"
            },
            "description": "One level: deeper replies are flattened under their top-level comment."
          },
          "canReply": {
            "type": "boolean"
          },
          "url": {
            "type": [
              "string",
              "null"
            ]
          },
          "mention": {
            "type": "string",
            "description": "Mastodon: start a reply with this for the author to be notified."
          },
          "isOwn": {
            "type": "boolean",
            "description": "Written by the connected account itself."
          }
        }
      },
      "CommentList": {
        "type": "object",
        "required": [
          "postId",
          "platform",
          "accountId",
          "comments",
          "nextCursor",
          "reply"
        ],
        "properties": {
          "postId": {
            "type": "string"
          },
          "platform": {
            "type": "string"
          },
          "accountId": {
            "type": "string"
          },
          "comments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Comment"
            },
            "description": "Newest first; replies oldest first."
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page. Null on networks that answer with the whole thread."
          },
          "reply": {
            "type": "object",
            "required": [
              "allowed",
              "topLevel"
            ],
            "properties": {
              "allowed": {
                "type": "boolean"
              },
              "topLevel": {
                "type": "boolean",
                "description": "A reply to the post itself (no `commentId`) is allowed."
              },
              "reason": {
                "type": "string",
                "description": "Why replies are not allowed, as a stable code."
              },
              "message": {
                "type": "string"
              }
            }
          },
          "olderThanSearchWindow": {
            "type": "boolean",
            "description": "X: the post is older than the 7 days recent search reaches, so earlier replies are missing from `comments`. Present only when true."
          },
          "note": {
            "type": "string",
            "description": "Why the list may be incomplete, in plain English. Present with `olderThanSearchWindow`."
          },
          "cachedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "X: served from the 10-minute cache; when it was read from the network."
          }
        }
      },
      "CommentReplied": {
        "type": "object",
        "required": [
          "postId",
          "platform",
          "comment"
        ],
        "properties": {
          "postId": {
            "type": "string"
          },
          "platform": {
            "type": "string"
          },
          "comment": {
            "$ref": "#/components/schemas/Comment"
          }
        }
      },
      "CommentReplyBody": {
        "type": "object",
        "required": [
          "text"
        ],
        "properties": {
          "text": {
            "type": "string",
            "description": "The reply, held to the network's character limit."
          },
          "commentId": {
            "type": "string",
            "description": "The comment to answer. Omit to reply to the post itself."
          }
        }
      },
      "ConnectUrls": {
        "type": "object",
        "required": [
          "object",
          "workspaceId",
          "urls",
          "alreadyConnected",
          "notConnected",
          "expiresAt"
        ],
        "properties": {
          "object": {
            "const": "connect_urls"
          },
          "workspaceId": {
            "type": "string"
          },
          "urls": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Keyed by platform."
          },
          "alreadyConnected": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "notConnected": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "requirements": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "What an account must be for its connect to succeed."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "DiscoveredPosts": {
        "type": "object",
        "required": [
          "object",
          "accountId",
          "platform",
          "source",
          "posts",
          "postCount"
        ],
        "properties": {
          "object": {
            "const": "discovered_posts"
          },
          "accountId": {
            "type": "string",
            "description": "The account whose sign-in made the read."
          },
          "workspaceId": {
            "type": "string"
          },
          "platform": {
            "type": "string"
          },
          "accountName": {
            "type": "string"
          },
          "accountHandle": {
            "type": "string"
          },
          "source": {
            "enum": [
              "search",
              "account"
            ]
          },
          "query": {
            "type": "string"
          },
          "handle": {
            "type": "string"
          },
          "sinceDays": {
            "type": "integer"
          },
          "cached": {
            "type": "boolean",
            "description": "Served from the copy kept for a day."
          },
          "scoreBasis": {
            "enum": [
              "followers",
              "set",
              "author",
              null
            ],
            "description": "What `outlierScore` compares against: engagement per follower across the results, the raw signal across them, or the creator’s own median."
          },
          "unsupported": {
            "const": true,
            "description": "This network gives apps no way to read other people’s posts."
          },
          "unsupportedReason": {
            "type": "string"
          },
          "note": {
            "type": "string",
            "description": "Something the read could not honour as asked."
          },
          "posts": {
            "type": "array",
            "description": "Best `outlierScore` first.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "text": {
                  "type": "string"
                },
                "url": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "author": {
                  "type": "object",
                  "properties": {
                    "handle": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "followers": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    }
                  }
                },
                "publishedAt": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "format": {
                  "enum": [
                    "text",
                    "image",
                    "carousel",
                    "video",
                    "link"
                  ]
                },
                "metrics": {
                  "type": "object",
                  "description": "The public counters the network shows: likes, comments, shares, quotes, bookmarks, views."
                },
                "signal": {
                  "type": "number",
                  "description": "Likes + comments + shares (+ quotes, bookmarks), or views on YouTube."
                },
                "outlierScore": {
                  "type": "number",
                  "description": "How many times its usual the post did; 1 is typical."
                },
                "traits": {
                  "type": "object",
                  "properties": {
                    "length": {
                      "type": "string"
                    },
                    "firstLine": {
                      "type": "string"
                    },
                    "hashtags": {
                      "type": "integer"
                    },
                    "hasLink": {
                      "type": "boolean"
                    },
                    "hasQuestion": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "postCount": {
            "type": "integer"
          }
        }
      },
      "EngagementHistory": {
        "type": "object",
        "required": [
          "object",
          "schema",
          "rows",
          "rowCount",
          "workspaceId",
          "days"
        ],
        "properties": {
          "object": {
            "const": "engagement_history"
          },
          "schema": {
            "type": "object",
            "description": "Column names and BigQuery-style types (STRING, INTEGER, DATE, BOOL); every column is NULLABLE.",
            "properties": {
              "fields": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string"
                    },
                    "mode": {
                      "const": "NULLABLE"
                    }
                  }
                }
              }
            }
          },
          "rows": {
            "type": "array",
            "description": "Workspace: date, platform (`all` for the day), likes, comments, shares, impressions, reachBasis, reach, saves, clicks, bookmarks, linkClicks, profileVisits, follows, watchTimeSeconds, degraded, awaitingPermission. Post: date, platform, cumulative* and daily* for each counter, spanDays, unreadableFields, awaitingPermission.",
            "items": {
              "type": "object",
              "additionalProperties": {
                "type": [
                  "string",
                  "number",
                  "boolean",
                  "null"
                ]
              }
            }
          },
          "rowCount": {
            "type": "integer"
          },
          "workspaceId": {
            "type": "string"
          },
          "postId": {
            "type": "string",
            "description": "With `postId` only."
          },
          "days": {
            "type": [
              "integer",
              "null"
            ]
          },
          "startDate": {
            "type": "string",
            "format": "date"
          },
          "endDate": {
            "type": "string",
            "format": "date"
          },
          "platforms": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "platformTotals": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "additionalProperties": {
                "type": "number"
              }
            }
          },
          "rangeTotals": {
            "type": "object",
            "additionalProperties": {
              "type": [
                "number",
                "null"
              ]
            }
          },
          "followers": {
            "type": "object",
            "description": "A second table, one row per (date, account): date, accountId, accountName, platform, followers (null, never 0, when not counted), dailyChange, approximate, unavailableReason."
          },
          "message": {
            "type": "string",
            "description": "Present when there is no daily data yet."
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "type",
              "code",
              "message"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "authentication_error",
                  "permission_error",
                  "invalid_request_error",
                  "rate_limit_error",
                  "api_error"
                ]
              },
              "code": {
                "type": "string",
                "description": "Stable identifier to branch on. See /docs/api/errors."
              },
              "message": {
                "type": "string",
                "description": "For a human reading a log; may change."
              },
              "param": {
                "type": "string",
                "description": "The offending field, when one can be named."
              },
              "tiktokChoices": {
                "$ref": "#/components/schemas/TikTokChoices"
              },
              "problems": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "field": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "description": "`tiktok_choices_needed` after settings were sent: what was wrong with each."
              },
              "settingsUrl": {
                "type": "string",
                "description": "`tiktok_choices_needed`: the post in the composer with its settings open."
              }
            }
          }
        }
      },
      "Media": {
        "type": "object",
        "required": [
          "object",
          "id",
          "workspaceId",
          "url",
          "name",
          "type"
        ],
        "properties": {
          "object": {
            "const": "media"
          },
          "id": {
            "type": "string"
          },
          "workspaceId": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "description": "What `media` on a post takes."
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "image",
              "video",
              "document"
            ]
          },
          "size": {
            "type": "integer"
          },
          "durationSec": {
            "type": [
              "number",
              "null"
            ]
          },
          "uploadedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "MediaCreate": {
        "type": "object",
        "description": "Exactly one of `url` and `upload`.",
        "properties": {
          "url": {
            "type": "string",
            "description": "A public link to the image, video or PDF itself; the server fetches it."
          },
          "upload": {
            "type": "object",
            "required": [
              "filename",
              "mimeType",
              "size"
            ],
            "description": "A file you hold: the answer is a one-time `uploadUrl` to PUT its bytes to.",
            "properties": {
              "filename": {
                "type": "string"
              },
              "mimeType": {
                "type": "string",
                "enum": [
                  "image/png",
                  "image/jpeg",
                  "image/gif",
                  "image/webp",
                  "image/avif",
                  "video/mp4",
                  "video/quicktime",
                  "video/webm",
                  "application/pdf"
                ]
              },
              "size": {
                "type": "integer",
                "description": "Bytes. Images up to 10 MB, video and PDF up to 1 GB."
              }
            }
          },
          "workspaceId": {
            "type": "string",
            "description": "Required when the account has more than one workspace."
          },
          "attachToPostIds": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "type": "string"
            },
            "description": "Posts to append the file to."
          }
        }
      },
      "MediaCreated": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Media"
          },
          {
            "type": "object",
            "properties": {
              "attached": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "With `attachToPostIds`: the posts it was added to."
              },
              "notAttached": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "postId": {
                      "type": "string"
                    },
                    "reason": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "description": "With `attachToPostIds`: the posts it was not added to, and why (a published post)."
              }
            }
          }
        ]
      },
      "MediaDeleted": {
        "type": "object",
        "required": [
          "object",
          "id",
          "deleted"
        ],
        "properties": {
          "object": {
            "const": "media_deleted"
          },
          "id": {
            "type": "string"
          },
          "deleted": {
            "const": true
          }
        }
      },
      "MediaList": {
        "type": "object",
        "required": [
          "object",
          "media",
          "nextCursor"
        ],
        "properties": {
          "object": {
            "const": "list"
          },
          "media": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Media"
            }
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "MediaUpload": {
        "type": "object",
        "required": [
          "object",
          "uploadUrl",
          "method",
          "expiresAt",
          "attachesTo",
          "maxBytes"
        ],
        "properties": {
          "object": {
            "const": "media_upload"
          },
          "uploadUrl": {
            "type": "string",
            "description": "PUT the raw bytes here, once. Its JSON answer has the `mediaId` and `url`."
          },
          "method": {
            "const": "PUT"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Start the upload before this; a long upload may finish after it."
          },
          "attachesTo": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The posts the file is appended to when it lands."
          },
          "maxBytes": {
            "type": "integer"
          }
        }
      },
      "MetricCell": {
        "type": "object",
        "required": [
          "value",
          "state"
        ],
        "properties": {
          "value": {
            "type": [
              "number",
              "null"
            ],
            "description": "Null unless `state` is `measured`; never 0 for unknown."
          },
          "state": {
            "type": "string",
            "description": "`measured`, `unsupported` (the platform cannot supply it), `unreadable` (a carried-forward value), or not yet measured."
          },
          "basis": {
            "type": "string"
          },
          "reason": {
            "type": "string"
          },
          "asOf": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Performance": {
        "type": "object",
        "required": [
          "object",
          "workspaceId",
          "window",
          "platforms",
          "rows",
          "rowCount"
        ],
        "properties": {
          "object": {
            "const": "performance"
          },
          "workspaceId": {
            "type": "string"
          },
          "window": {
            "type": "object",
            "properties": {
              "from": {
                "type": "string"
              },
              "to": {
                "type": "string"
              }
            }
          },
          "accounts": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "platforms": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "platform": {
                  "type": "string"
                },
                "postCount": {
                  "type": "integer"
                },
                "totals": {
                  "type": "object",
                  "additionalProperties": {
                    "type": [
                      "number",
                      "null"
                    ]
                  }
                },
                "engagement": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "rate": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "skipped": {
                  "type": "integer"
                },
                "syncedAt": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "oldestAsOf": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          },
          "rows": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "postId": {
                  "type": "string"
                },
                "platform": {
                  "type": "string"
                },
                "text": {
                  "type": "string"
                },
                "publishedAt": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "accountId": {
                  "type": "string"
                },
                "campaignId": {
                  "type": "string"
                },
                "goal": {
                  "type": "string",
                  "description": "The post's goal, when it has one."
                },
                "metrics": {
                  "type": "object",
                  "additionalProperties": {
                    "$ref": "#/components/schemas/MetricCell"
                  }
                },
                "engagement": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "rate": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "degraded": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "rowCount": {
            "type": "integer"
          },
          "degradedRows": {
            "type": "integer"
          },
          "previous": {
            "type": "array",
            "description": "With `compare`: the platform totals over the preceding window."
          },
          "findings": {
            "$ref": "#/components/schemas/PerformanceFindings"
          }
        }
      },
      "PerformanceFindings": {
        "type": "object",
        "description": "With `findings`: what the window says, each a comparison of numbers in the report, with a floor below which it says there is not enough data. The same block MCP get_performance returns.",
        "properties": {
          "timezone": {
            "type": "string",
            "description": "The workspace timezone the weekdays and hours are in."
          },
          "comparison": {
            "type": "object",
            "description": "Per platform, this window against the preceding one of equal length. Reach is compared only when both windows count the same thing (`basis`).",
            "properties": {
              "previousFrom": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "previousTo": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "platforms": {
                "type": "array",
                "items": {
                  "type": "object"
                }
              }
            }
          },
          "ranking": {
            "type": "object",
            "description": "The top and bottom three posts by engagement rate, and the traits most of the top ones share and fewer bottom ones do; `enoughData: false` under six rated posts."
          },
          "bestWindows": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Per account: windows from its own posts, or labelled fallbacks when it has too few."
          },
          "followers": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Per account: first and last measured follower count in the window, the `change` and `changePct` (null from zero)."
          },
          "postAgainToday": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Per account: posts in the last 24 hours, scheduled in the next 24, the usual count on posting days, and the daily cap."
          },
          "growth": {
            "type": "object",
            "description": "Which posts brought followers: `measuredPosts`, `follows` (summed), up to three `topPosts` with `follows` and `profileVisits`, `sharedTraits` they have and the rest lack, and `notMeasuredOn` (platforms that report no per-post follows). `days`: on every platform with a follower count, per account the stretches between two counts with the most growth per day and the posts published in each (`best`), followers per day over stretches with posts and without (`withPosts`, `withoutPosts`), the `sharedTraits` of the posts in the best stretches, `enoughData` (from `needed` stretches) and `basis`: what coincided with growth, not proof of cause."
          },
          "digest": {
            "type": "object",
            "description": "The window as a report: `published` (total, per platform), `engagement` against the previous window, `topPost`, net `followers` (with `changePct`), `failed`, `scheduledNext7Days`, and `lines`, the same in sentences."
          }
        }
      },
      "Platform": {
        "type": "object",
        "required": [
          "object",
          "id",
          "name",
          "text",
          "media",
          "dailyPostCap",
          "mentions",
          "settings"
        ],
        "properties": {
          "object": {
            "const": "platform"
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "text": {
            "type": "object",
            "properties": {
              "limit": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "required": {
                "type": "boolean"
              },
              "counting": {
                "type": "string",
                "enum": [
                  "weighted",
                  "graphemes",
                  "characters"
                ]
              }
            }
          },
          "media": {
            "type": "object",
            "properties": {
              "required": {
                "type": "boolean"
              },
              "maxItems": {
                "type": "integer"
              },
              "canMixImageAndVideo": {
                "type": "boolean"
              },
              "types": {
                "type": "object",
                "additionalProperties": {
                  "type": "object",
                  "properties": {
                    "extensions": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "mimeTypes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "maxSizeBytes": {
                      "type": "integer"
                    },
                    "maxItems": {
                      "type": "integer"
                    },
                    "maxDurationSeconds": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "aspectRatios": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "dailyPostCap": {
            "type": "object",
            "properties": {
              "free": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "paid": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "mentions": {
            "type": "object",
            "properties": {
              "links": {
                "type": "string"
              },
              "maxPerPost": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "derivedTitleLimit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "settings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SettingField"
            }
          }
        }
      },
      "PlatformList": {
        "type": "object",
        "required": [
          "object",
          "platforms"
        ],
        "properties": {
          "object": {
            "const": "list"
          },
          "platforms": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Platform"
            }
          }
        }
      },
      "PlatformPosts": {
        "type": "object",
        "required": [
          "object",
          "accountId",
          "platform",
          "posts",
          "postCount"
        ],
        "properties": {
          "object": {
            "const": "platform_posts"
          },
          "accountId": {
            "type": "string"
          },
          "workspaceId": {
            "type": "string"
          },
          "platform": {
            "type": "string"
          },
          "accountName": {
            "type": "string"
          },
          "accountHandle": {
            "type": "string"
          },
          "unsupported": {
            "const": true,
            "description": "This account cannot be read back (a LinkedIn personal profile)."
          },
          "unsupportedReason": {
            "type": "string"
          },
          "cachedAt": {
            "type": "string",
            "description": "X only: these posts come from a read made at this time and kept up to a week (X bills per post read). Publishing through Antwork drops the kept read."
          },
          "posts": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "text": {
                  "type": "string"
                },
                "publishedAt": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "engagementMetrics": {
                  "type": [
                    "object",
                    "null"
                  ]
                },
                "mediaType": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "permalink": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          },
          "postCount": {
            "type": "integer"
          }
        }
      },
      "PlatformPostsFetch": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "maxPosts": {
            "type": "integer",
            "minimum": 1,
            "maximum": 25,
            "default": 10,
            "description": "Posts to return."
          },
          "source": {
            "enum": [
              "own",
              "search",
              "account"
            ],
            "default": "own",
            "description": "`own`: this account’s posts. `search` / `account`: other people’s public posts on this account’s network, read with its sign-in (paid plans)."
          },
          "query": {
            "type": "string",
            "maxLength": 200,
            "description": "With `source: \"search\"`: keywords or a `#hashtag`."
          },
          "handle": {
            "type": "string",
            "maxLength": 200,
            "description": "With `source: \"account\"`: the creator’s handle (`user@server` on Mastodon)."
          },
          "sinceDays": {
            "type": "integer",
            "minimum": 1,
            "maximum": 30,
            "description": "How far back. Default 7 for a search, 30 for a creator; X search reaches back 7."
          }
        }
      },
      "Post": {
        "type": "object",
        "required": [
          "object",
          "id",
          "workspaceId",
          "status",
          "text",
          "mediaUrls"
        ],
        "properties": {
          "object": {
            "const": "post"
          },
          "id": {
            "type": "string"
          },
          "workspaceId": {
            "type": "string"
          },
          "accountId": {
            "type": [
              "string",
              "null"
            ]
          },
          "platform": {
            "type": [
              "string",
              "null"
            ]
          },
          "campaignId": {
            "type": [
              "string",
              "null"
            ]
          },
          "goal": {
            "type": [
              "string",
              "null"
            ],
            "description": "The goal the post is tagged with (Educate, Promote, …)."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "scheduled",
              "published",
              "failed",
              "pending_approval"
            ],
            "description": "`pending_approval`: the workspace requires approval and a person has not approved it yet. It is not queued; it goes out once approved in the Antwork app."
          },
          "text": {
            "type": "string"
          },
          "mediaUrls": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scheduledFor": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "publishedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "publishedUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "platformPostId": {
            "type": [
              "string",
              "null"
            ]
          },
          "error": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "message": {
                "type": "string"
              },
              "advice": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "approval": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/PostApproval"
              },
              {
                "type": "null"
              }
            ],
            "description": "Null unless the workspace requires approval and the post was sent for it."
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "PostApproval": {
        "type": "object",
        "required": [
          "state"
        ],
        "properties": {
          "state": {
            "type": "string",
            "enum": [
              "pending",
              "approved",
              "changes_requested"
            ],
            "description": "`changes_requested`: the reviewer sent it back as a draft; change it as `note` asks and send it again."
          },
          "note": {
            "type": "string",
            "description": "With `changes_requested`: what the reviewer asked to change."
          },
          "decidedBy": {
            "type": "string",
            "description": "The client link's name for a decision made through it, `admin` for one in the Antwork app."
          },
          "decidedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "requestedFor": {
            "type": "string",
            "description": "`pending` only: the time the held send asked for (ISO 8601), or `now`."
          }
        }
      },
      "PostBatch": {
        "type": "object",
        "required": [
          "object",
          "campaignId",
          "posts"
        ],
        "properties": {
          "object": {
            "const": "post_batch"
          },
          "campaignId": {
            "type": [
              "string",
              "null"
            ]
          },
          "posts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PostResult"
            }
          }
        }
      },
      "PostDeleted": {
        "type": "object",
        "required": [
          "object",
          "id",
          "softDeleted"
        ],
        "properties": {
          "object": {
            "const": "post_deleted"
          },
          "id": {
            "type": "string"
          },
          "softDeleted": {
            "type": "boolean"
          },
          "platformDeletionQueuedFor": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "platformDeletionUnsupported": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "PostDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Post"
          },
          {
            "type": "object",
            "required": [
              "readiness",
              "editUrl",
              "settingsUrl"
            ],
            "properties": {
              "readiness": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/PostReadiness"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "What it still needs before it can publish. Null once published."
              },
              "editUrl": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The post in the Antwork web composer."
              },
              "settingsUrl": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The same, with its platform settings open."
              }
            }
          }
        ]
      },
      "PostEntry": {
        "type": "object",
        "required": [
          "accountId"
        ],
        "properties": {
          "accountId": {
            "type": "string",
            "description": "An account id from GET /accounts. Named twice, two variants."
          },
          "text": {
            "type": "string"
          },
          "goal": {
            "type": "string",
            "description": "A goal to tag the post with, e.g. Educate, Engage, Promote, Entertain."
          },
          "hashtags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Added to the text where the platform publishes them."
          },
          "userTags": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "LinkedIn company Pages (`{company}`) or Instagram people (`{type: \"photo_tag\", username, x, y}`)."
          },
          "media": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Files in this workspace's media library: media ids or URLs."
          },
          "options": {
            "type": "object",
            "description": "This post's platform settings, unkeyed (`{privacyStatus: 'unlisted'}`, Pinterest `{boardId}`, Slack `{channel}`: a channel id or #name from the account's `slackChannels`). For a TikTok post, the user's choices in the `TikTokSettings` shape."
          }
        }
      },
      "PostingSettings": {
        "type": "object",
        "description": "The account owner’s own posting rules, enforced like the platform caps (`account_limit_reached`): a daily maximum under the platform’s, a minimum gap between posts, and weekly slots that `scheduledFor: \"next_slot\"` fills.",
        "properties": {
          "maxPostsPerDay": {
            "type": "integer",
            "minimum": 1,
            "description": "At most this many posts in any 24 hours, at most the platform’s cap."
          },
          "minGapMinutes": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1440
          },
          "timezone": {
            "type": "string",
            "description": "IANA zone of `slots`; the workspace’s when absent, else UTC."
          },
          "slots": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "object",
              "required": [
                "day",
                "time"
              ],
              "properties": {
                "day": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 7,
                  "description": "1 = Monday … 7 = Sunday."
                },
                "time": {
                  "type": "string",
                  "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                  "description": "Local time, HH:MM."
                }
              }
            }
          }
        }
      },
      "PostList": {
        "type": "object",
        "required": [
          "object",
          "posts",
          "nextCursor"
        ],
        "properties": {
          "object": {
            "const": "list"
          },
          "posts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Post"
            }
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page; null on the last."
          }
        }
      },
      "PostMedia": {
        "type": "object",
        "required": [
          "media"
        ],
        "properties": {
          "media": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "type": "string"
            },
            "description": "Media ids or URLs from this workspace's library, in order. `[]` clears them."
          }
        }
      },
      "PostReadiness": {
        "type": "object",
        "required": [
          "characterCount",
          "characterLimit",
          "overLimit",
          "mediaRequired",
          "settingsRequired",
          "publishBlocker"
        ],
        "properties": {
          "characterCount": {
            "type": "integer"
          },
          "characterLimit": {
            "type": [
              "integer",
              "null"
            ]
          },
          "overLimit": {
            "type": "boolean"
          },
          "mediaRequired": {
            "type": "boolean"
          },
          "settingsRequired": {
            "type": "boolean",
            "description": "A setting only the account owner picks (TikTok audience) is unset."
          },
          "publishBlocker": {
            "type": [
              "string",
              "null"
            ],
            "description": "The rejection reason a publish would get now, or null."
          }
        }
      },
      "PostResult": {
        "type": "object",
        "required": [
          "object",
          "id",
          "accountId",
          "platform",
          "status",
          "reason",
          "message",
          "readiness",
          "editUrl",
          "settingsUrl"
        ],
        "properties": {
          "object": {
            "const": "post_result"
          },
          "id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Null when the target was rejected before anything was written."
          },
          "accountId": {
            "type": [
              "string",
              "null"
            ]
          },
          "platform": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "accepted",
              "rejected",
              "failed"
            ]
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "A rejection reason from /docs/api/errors."
          },
          "message": {
            "type": [
              "string",
              "null"
            ]
          },
          "readiness": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/PostReadiness"
              },
              {
                "type": "null"
              }
            ],
            "description": "What the post still needs before it can publish. Null when nothing was written."
          },
          "editUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "The post in the Antwork composer."
          },
          "settingsUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "The post in the composer with its settings open."
          },
          "retried": {
            "type": "boolean",
            "description": "Campaign publish only: a failed post was requeued (its retry)."
          },
          "pendingApproval": {
            "type": "boolean",
            "description": "Accepted for approval, not for publishing: the workspace requires approval, so the post is `pending_approval` and goes out once a person approves it in the Antwork app."
          },
          "similarRecent": {
            "type": "array",
            "description": "Near-duplicates of this post on the same account from the last 30 days (shared distinct words, Jaccard ≥ 0.6), most similar first, at most 3. A hint, never a refusal.",
            "items": {
              "type": "object",
              "properties": {
                "postId": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                },
                "at": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "similarity": {
                  "type": "number"
                },
                "excerpt": {
                  "type": "string"
                }
              }
            }
          },
          "tiktokChoices": {
            "$ref": "#/components/schemas/TikTokChoices"
          },
          "problems": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "With `tiktok_choices_needed` after settings were sent."
          },
          "tagChecks": {
            "type": "array",
            "description": "Instagram posts with `photo_tag` userTags: each handle looked up on Instagram. `found` carries the profile; `unchecked` means Instagram would not say (personal and age-gated accounts cannot be looked up), not that the handle is wrong.",
            "items": {
              "type": "object",
              "required": [
                "username",
                "status"
              ],
              "properties": {
                "username": {
                  "type": "string"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "found",
                    "unchecked"
                  ]
                },
                "name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "pictureUrl": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          }
        }
      },
      "PostSent": {
        "allOf": [
          {
            "$ref": "#/components/schemas/PostDetail"
          },
          {
            "type": "object",
            "required": [
              "retried"
            ],
            "properties": {
              "retried": {
                "type": "boolean",
                "description": "The post had failed and was requeued (a retry) rather than sent fresh."
              }
            }
          }
        ]
      },
      "PostUnscheduled": {
        "allOf": [
          {
            "$ref": "#/components/schemas/PostDetail"
          },
          {
            "type": "object",
            "required": [
              "unscheduled"
            ],
            "properties": {
              "unscheduled": {
                "type": "boolean",
                "description": "False when the post was not scheduled: nothing changed."
              }
            }
          }
        ]
      },
      "PostUpdate": {
        "type": "object",
        "minProperties": 1,
        "additionalProperties": false,
        "properties": {
          "text": {
            "type": "string",
            "description": "The new text. Hashtags already in it stay."
          },
          "hashtags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Added to the text where the platform publishes them (YouTube keeps them as tags)."
          },
          "goal": {
            "type": "string",
            "description": "A goal to tag the post with, e.g. Educate, Engage, Promote, Entertain."
          },
          "accountId": {
            "type": "string",
            "description": "Move the post to this account; its platform follows."
          },
          "options": {
            "type": [
              "object",
              "null"
            ],
            "description": "Platform settings to set, unkeyed (`{privacyStatus: 'unlisted'}`, Pinterest `{boardId}`, Slack `{channel}`: an id or #name). A key given `null` is removed; `null` removes them all."
          },
          "newBoardName": {
            "type": "string",
            "description": "Pinterest: create a board with this name on the account and pin to it."
          },
          "scheduledFor": {
            "type": "string",
            "format": "date-time",
            "description": "A scheduled post moves to this time; a draft only keeps it as a proposal."
          },
          "status": {
            "const": "draft",
            "description": "Move a scheduled post back to draft (its queued publish is cancelled)."
          }
        }
      },
      "PublishBody": {
        "type": "object",
        "properties": {
          "tiktokSettings": {
            "$ref": "#/components/schemas/TikTokSettings"
          }
        }
      },
      "Recurrence": {
        "type": "object",
        "description": "A post set to repeat, or in its account's evergreen queue. The id is the source post's.",
        "required": [
          "object",
          "id",
          "sourcePostId",
          "workspaceId",
          "kind",
          "status",
          "platform",
          "accountId",
          "made",
          "variants"
        ],
        "properties": {
          "object": {
            "const": "recurrence"
          },
          "id": {
            "type": "string"
          },
          "sourcePostId": {
            "type": "string"
          },
          "workspaceId": {
            "type": "string"
          },
          "kind": {
            "enum": [
              "repeat",
              "evergreen"
            ]
          },
          "status": {
            "enum": [
              "active",
              "paused",
              "ended"
            ]
          },
          "statusReason": {
            "type": "string",
            "description": "Why Antwork paused or ended it: `plan`, `source_deleted`, `finished`, `unsupported_platform`."
          },
          "platform": {
            "type": "string"
          },
          "accountId": {
            "type": "string"
          },
          "repeat": {
            "$ref": "#/components/schemas/RepeatRule"
          },
          "nextAt": {
            "type": "string",
            "format": "date-time",
            "description": "A repeat's next post time."
          },
          "evergreenPerWeek": {
            "type": "integer",
            "description": "Evergreen posts per week on this account."
          },
          "made": {
            "type": "integer",
            "description": "Posts made so far."
          },
          "variants": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "lastScheduledFor": {
            "type": "string",
            "format": "date-time"
          },
          "lastPostId": {
            "type": "string"
          },
          "lastSkip": {
            "type": "object",
            "description": "The last occurrence that was not made, and why (`duplicate_post`, `daily_cap_reached`, `no_posting_slots`, `missed`, …).",
            "properties": {
              "reason": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "RecurrenceDeleted": {
        "type": "object",
        "required": [
          "object",
          "id",
          "deleted"
        ],
        "properties": {
          "object": {
            "const": "recurrence_deleted"
          },
          "id": {
            "type": "string"
          },
          "deleted": {
            "const": true
          }
        }
      },
      "RecurrenceList": {
        "type": "object",
        "required": [
          "object",
          "recurrences"
        ],
        "properties": {
          "object": {
            "const": "list"
          },
          "recurrences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Recurrence"
            }
          }
        }
      },
      "RepeatRule": {
        "type": "object",
        "required": [
          "every",
          "unit"
        ],
        "properties": {
          "every": {
            "type": "integer",
            "minimum": 1,
            "description": "1–365 days or 1–52 weeks."
          },
          "unit": {
            "enum": [
              "day",
              "week"
            ]
          },
          "until": {
            "type": "string",
            "format": "date-time",
            "description": "No post after this time."
          },
          "count": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "description": "How many more posts, the original not counted."
          },
          "description": {
            "type": "string",
            "readOnly": true
          }
        }
      },
      "ScheduleBody": {
        "type": "object",
        "required": [
          "scheduledFor"
        ],
        "properties": {
          "scheduledFor": {
            "type": "string",
            "description": "When to publish: an ISO 8601 date-time in the future (Free: at most 30 days ahead; paid plans: any time), or `\"next_slot\"` for the account’s next free posting slot (`posting.slots`; the answer names it in `slot`)."
          },
          "tiktokSettings": {
            "$ref": "#/components/schemas/TikTokSettings"
          }
        }
      },
      "SettingField": {
        "type": "object",
        "required": [
          "key",
          "label",
          "type"
        ],
        "properties": {
          "key": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "enum",
              "bool",
              "text",
              "url"
            ]
          },
          "options": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                }
              }
            }
          },
          "default": {},
          "maxLength": {
            "type": "integer"
          },
          "placeholder": {
            "type": "string"
          }
        }
      },
      "TikTokAnswers": {
        "type": "object",
        "description": "The user's own choices for one TikTok post, asked from the `tiktokChoices` of a `tiktok_choices_needed` refusal. Checked against the creator's live options; never chosen for the user.",
        "required": [
          "privacyLevel",
          "allowComment",
          "commercialContent",
          "userConsented"
        ],
        "properties": {
          "privacyLevel": {
            "type": "string",
            "description": "One of `tiktokChoices.privacyLevel.options`. No default."
          },
          "allowComment": {
            "type": "boolean"
          },
          "allowDuet": {
            "type": "boolean",
            "description": "Required for a video."
          },
          "allowStitch": {
            "type": "boolean",
            "description": "Required for a video."
          },
          "commercialContent": {
            "type": "object",
            "required": [
              "enabled"
            ],
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "yourBrand": {
                "type": "boolean",
                "description": "Labelled \"Promotional content\"."
              },
              "brandedContent": {
                "type": "boolean",
                "description": "Labelled \"Paid partnership\". Not with `SELF_ONLY`."
              }
            }
          },
          "aiGenerated": {
            "type": "boolean"
          },
          "userConsented": {
            "const": true,
            "description": "The user agreed to the declaration in `tiktokChoices.declaration`."
          }
        }
      },
      "TikTokChoices": {
        "type": "object",
        "description": "With `tiktok_choices_needed`: what to put in front of the user before a TikTok post goes. Build the UI from it; never pick for the user.",
        "properties": {
          "creator": {
            "type": "object",
            "properties": {
              "nickname": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "avatarUrl": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "privacyLevel": {
            "type": "object",
            "description": "No default: `default` is always null.",
            "properties": {
              "default": {
                "type": "null"
              },
              "options": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "value": {
                      "type": "string"
                    },
                    "label": {
                      "type": "string"
                    }
                  }
                }
              },
              "notWithBrandedContent": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "interactions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "default": {
                  "const": false
                },
                "disabledByCreator": {
                  "type": "boolean"
                }
              }
            }
          },
          "commercialContent": {
            "type": "object",
            "description": "Off by default; once on, at least one of `yourBrand` / `brandedContent`, each with the label TikTok shows."
          },
          "aiGenerated": {
            "type": "object"
          },
          "maxVideoPostDurationSec": {
            "type": [
              "integer",
              "null"
            ]
          },
          "videoDurationSec": {
            "type": "number"
          },
          "declaration": {
            "type": "object",
            "description": "Shown, with its links, and agreed to before `userConsented: true` is sent.",
            "properties": {
              "text": {
                "type": "string"
              },
              "textWithBrandedContent": {
                "type": "string"
              },
              "links": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                }
              },
              "requiresConsent": {
                "const": true
              }
            }
          },
          "preview": {
            "type": "object",
            "properties": {
              "text": {
                "type": "string"
              },
              "mediaUrls": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "lastUsed": {
            "type": "object",
            "description": "The account's last answers that still apply, when it has some: ask the user once, then send `{useLast: true, userConsented: true}`.",
            "properties": {
              "settings": {
                "type": "object"
              },
              "summary": {
                "type": "string"
              }
            }
          },
          "nextStep": {
            "type": "string"
          }
        }
      },
      "TikTokSettings": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/TikTokAnswers"
          },
          {
            "$ref": "#/components/schemas/TikTokUseLast"
          }
        ],
        "description": "The user's choices for one TikTok post: each answer, or `useLast` once they said yes to the `lastUsed` settings offered."
      },
      "TikTokUseLast": {
        "type": "object",
        "description": "The account's last answers (`tiktokChoices.lastUsed`), re-checked against the creator's live options. Send only after the user said yes to them for this post; nothing stored applies without it.",
        "required": [
          "useLast",
          "userConsented"
        ],
        "additionalProperties": false,
        "properties": {
          "useLast": {
            "const": true
          },
          "userConsented": {
            "const": true,
            "description": "The user agreed to their usual settings and the declaration for this post."
          }
        }
      },
      "Usage": {
        "type": "object",
        "required": [
          "object",
          "plan",
          "posts",
          "workspaces"
        ],
        "properties": {
          "object": {
            "const": "usage"
          },
          "plan": {
            "type": "string"
          },
          "posts": {
            "type": "object",
            "description": "Posts committed this billing cycle. With `unlimited: true` nothing is counted: `used` is 0, `limit` and `remaining` null.",
            "properties": {
              "used": {
                "type": "integer"
              },
              "limit": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "remaining": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "unlimited": {
                "type": "boolean"
              },
              "cycleStart": {
                "type": "string",
                "format": "date-time"
              },
              "cycleEnd": {
                "type": "string",
                "format": "date-time"
              },
              "usageUnavailable": {
                "const": true,
                "description": "The count could not be taken; `used` is unknown."
              }
            }
          },
          "workspaces": {
            "type": "object",
            "properties": {
              "used": {
                "type": "integer"
              },
              "limit": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "remaining": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "unlimited": {
                "type": "boolean"
              }
            }
          },
          "billing": {
            "type": "object",
            "description": "Where to change the plan and what is time-limited or scheduled. Present for accounts on the Free/Pro/Business/Scale/Agency plans.",
            "required": [
              "billingUrl"
            ],
            "properties": {
              "billingUrl": {
                "type": "string",
                "format": "uri",
                "description": "The plan page: upgrade, switch, cancel, claim the founding offer."
              },
              "interval": {
                "enum": [
                  "month",
                  "year"
                ],
                "description": "A paid plan's billing period."
              },
              "renewsAt": {
                "type": "string",
                "format": "date-time",
                "description": "When a paid plan renews, or ends if `cancelsAtPeriodEnd`."
              },
              "cancelsAtPeriodEnd": {
                "const": true,
                "description": "The paid plan moves to Free at `renewsAt`."
              },
              "scheduledChange": {
                "type": "object",
                "description": "A downgrade waiting for the renewal.",
                "properties": {
                  "plan": {
                    "type": "string"
                  },
                  "interval": {
                    "enum": [
                      "month",
                      "year"
                    ]
                  },
                  "at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  }
                }
              },
              "foundingOffer": {
                "type": "object",
                "description": "`percentOff` off the first year of any yearly plan, bought before `endsAt`. Only while the account can still take it.",
                "properties": {
                  "percentOff": {
                    "type": "integer"
                  },
                  "endsAt": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              },
              "unlimitedPostsUntil": {
                "type": "string",
                "format": "date-time",
                "description": "Unlimited posts end then; Free allows `postsPerMonthAfter` a month after."
              },
              "postsPerMonthAfter": {
                "type": "integer"
              }
            }
          },
          "trialNotice": {
            "type": "object",
            "description": "The trial's end: present in its last 2 days (`ending`) and the week after the move to Free (`ended`). `userMessage` is one sentence for the user, with the plan page link.",
            "required": [
              "state",
              "plan",
              "endsAt",
              "free",
              "accountsPaused",
              "upgradeUrl",
              "userMessage",
              "instruction"
            ],
            "properties": {
              "state": {
                "enum": [
                  "ending",
                  "ended"
                ]
              },
              "plan": {
                "type": "string",
                "description": "The plan tried (`pro`, `business`, `scale`, `agency`)."
              },
              "endsAt": {
                "type": "string",
                "format": "date-time"
              },
              "daysLeft": {
                "type": "integer",
                "description": "Whole days until the end, rounded up. `ending` only."
              },
              "free": {
                "type": "object",
                "description": "What Free keeps.",
                "properties": {
                  "accounts": {
                    "type": "integer"
                  },
                  "postsPerMonth": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "analytics": {
                    "type": "boolean"
                  }
                }
              },
              "accountsPaused": {
                "type": "integer",
                "description": "`ending`: accounts that will pause. `ended`: accounts paused now."
              },
              "upgradeUrl": {
                "type": "string",
                "format": "uri"
              },
              "userMessage": {
                "type": "string"
              },
              "instruction": {
                "type": "string",
                "description": "For an AI caller: what to do with `userMessage`."
              }
            }
          }
        }
      },
      "Webhook": {
        "type": "object",
        "required": [
          "object",
          "id",
          "workspaceId",
          "url",
          "events",
          "status"
        ],
        "properties": {
          "object": {
            "const": "webhook"
          },
          "id": {
            "type": "string"
          },
          "workspaceId": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "enum": [
                "post.scheduled",
                "post.published",
                "post.failed",
                "account.needs_reconnect",
                "account.disconnected"
              ]
            }
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "enum": [
              "active",
              "disabled"
            ]
          },
          "disabledReason": {
            "type": [
              "string",
              "null"
            ],
            "description": "`consecutive_failures` when Antwork switched it off, `user` when you did."
          },
          "consecutiveFailures": {
            "type": "integer",
            "description": "Events in a row that ended undelivered. At 20 the endpoint is disabled."
          },
          "lastDeliveryAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "lastStatus": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The HTTP status of the last attempt, null when it never answered."
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "WebhookDeleted": {
        "type": "object",
        "required": [
          "object",
          "id",
          "deleted"
        ],
        "properties": {
          "object": {
            "const": "webhook_deleted"
          },
          "id": {
            "type": "string"
          },
          "deleted": {
            "const": true
          }
        }
      },
      "WebhookDeliveryList": {
        "type": "object",
        "required": [
          "object",
          "deliveries"
        ],
        "properties": {
          "object": {
            "const": "list"
          },
          "deliveries": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "object": {
                  "const": "webhook_delivery"
                },
                "id": {
                  "type": "string"
                },
                "eventId": {
                  "type": "string"
                },
                "type": {
                  "type": "string"
                },
                "attempt": {
                  "type": "integer"
                },
                "ok": {
                  "type": "boolean"
                },
                "final": {
                  "type": "boolean",
                  "description": "The attempt that ended this event: delivered, refused, or out of retries."
                },
                "status": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "latencyMs": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "error": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "createdAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                }
              }
            }
          }
        }
      },
      "WebhookList": {
        "type": "object",
        "required": [
          "object",
          "webhooks"
        ],
        "properties": {
          "object": {
            "const": "list"
          },
          "webhooks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Webhook"
            }
          }
        }
      },
      "WebhookTest": {
        "type": "object",
        "required": [
          "object",
          "eventId",
          "queued"
        ],
        "properties": {
          "object": {
            "const": "webhook_test"
          },
          "eventId": {
            "type": "string"
          },
          "queued": {
            "const": true
          }
        }
      },
      "WebhookWithSecret": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Webhook"
          },
          {
            "type": "object",
            "required": [
              "secret"
            ],
            "properties": {
              "secret": {
                "type": "string",
                "description": "`whsec_…`, shown this once. Verifies the `webhook-signature` header."
              }
            }
          }
        ]
      },
      "Workspace": {
        "type": "object",
        "required": [
          "object",
          "id",
          "name",
          "brandVersion"
        ],
        "properties": {
          "object": {
            "const": "workspace"
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "website": {
            "type": [
              "string",
              "null"
            ]
          },
          "logoUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "timezone": {
            "type": [
              "string",
              "null"
            ]
          },
          "preferredTimes": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^\\d{2}:\\d{2}$"
            },
            "description": "Preferred posting times, HH:MM in `timezone`."
          },
          "tagOutboundLinks": {
            "type": "boolean",
            "description": "UTM tags on links to the workspace's own website when a post publishes."
          },
          "brandVersion": {
            "type": "integer",
            "description": "Bumped when the identity or settings change."
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "WorkspaceList": {
        "type": "object",
        "required": [
          "object",
          "workspaces"
        ],
        "properties": {
          "object": {
            "const": "list"
          },
          "workspaces": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Workspace"
            }
          }
        }
      }
    }
  }
}
