{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/juzpost/json-schema/juzpost-schedule-post-request-schema.json",
  "title": "SchedulePostRequest",
  "description": "Which accounts to send one draft to, and when. Every key used in an overrides map must\nalso appear in `socialAccountIds`, or the whole request is rejected with `400`.\n",
  "x-generated": "2026-11-08",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/juzpost-openapi.json#/components/schemas/SchedulePostRequest",
  "type": "object",
  "required": [
    "socialAccountIds"
  ],
  "properties": {
    "socialAccountIds": {
      "type": "array",
      "minItems": 1,
      "maxItems": 10,
      "description": "The accounts to publish to, between one and ten. Duplicates are silently collapsed.\nIf any id is not yours the entire request fails with `404` and does not\npartially schedule.\n",
      "items": {
        "type": "string",
        "format": "uuid",
        "description": "A social account id from `GET /accounts`."
      }
    },
    "publishAt": {
      "type": "string",
      "format": "date-time",
      "description": "When to publish, as an ISO 8601 UTC instant. Must be at least 5 minutes and at most\nroughly 6 months in the future. Omit this field entirely to publish immediately, but\nthat path needs the `publish` capability instead of `schedule`.\n"
    },
    "title": {
      "type": "string",
      "maxLength": 100,
      "description": "Title to use for this run, overriding the stored one and persisted back onto the\npost. Note this limit is stricter than the 200 characters `POST /posts` accepts.\n"
    },
    "description": {
      "type": "string",
      "maxLength": 10000,
      "description": "Description to use for this run, overriding the stored one and persisted back onto\nthe post. Also re-checked against each target platform's own caption limit.\n"
    },
    "hashtags": {
      "type": "array",
      "maxItems": 30,
      "description": "Hashtags to use for this run, overriding the stored ones. Do not include the `#`.\n",
      "items": {
        "type": "string",
        "maxLength": 100,
        "description": "A single hashtag, without the `#`."
      }
    },
    "platformOverrides": {
      "type": "object",
      "description": "Per-account content overrides, keyed by social account id. Every key must be one of\nthe ids in `socialAccountIds`.\n",
      "additionalProperties": {
        "$ref": "#/$defs/PlatformOverride"
      }
    },
    "publishAtOverrides": {
      "type": "object",
      "description": "Per-account fire times, keyed by social account id, each an ISO 8601 UTC instant.\nAccounts not listed use the top-level `publishAt`. Every key must be one of the ids\nin `socialAccountIds`.\n",
      "additionalProperties": {
        "type": "string",
        "format": "date-time",
        "description": "The ISO 8601 UTC fire time for that one account."
      }
    },
    "tiktokSettings": {
      "type": "object",
      "description": "Per-account TikTok settings, keyed by social account id. Every key must be one of the\nids in `socialAccountIds`.\n",
      "additionalProperties": {
        "$ref": "#/$defs/TikTokSettings"
      }
    },
    "pinterestSettings": {
      "type": "object",
      "description": "Per-account Pinterest settings, keyed by social account id. Every key must be one of\nthe ids in `socialAccountIds`.\n",
      "additionalProperties": {
        "$ref": "#/$defs/PinterestSettings"
      }
    },
    "blueskySettings": {
      "type": "object",
      "description": "Per-account Bluesky alt text and content warnings, keyed by social account id. Every\nkey must be one of the ids in `socialAccountIds` and must name a Bluesky account.\n",
      "additionalProperties": {
        "$ref": "#/$defs/BlueskySettings"
      }
    },
    "wordpressSettings": {
      "type": "object",
      "description": "Per-account WordPress post settings for a `blog` post, keyed by social account id.\nEvery key must be one of the ids in `socialAccountIds` and must name a WordPress\naccount. Nothing reaches WordPress before the post fires.\n",
      "additionalProperties": {
        "$ref": "#/$defs/WordPressSettings"
      }
    }
  },
  "$defs": {
    "BlueskySettings": {
      "type": "object",
      "description": "Alt text for each file one Bluesky account publishes, and the content warning labels\non the post. Stored on that account's copy and returned on `GET /posts/{postId}`.\n",
      "required": [
        "altText",
        "labels"
      ],
      "properties": {
        "altText": {
          "type": "array",
          "maxItems": 4,
          "description": "One entry per file, in the order that account publishes them. Use an empty string\nfor a file with no description. The count must equal the number of files, or the\nrequest fails with `400`.\n",
          "items": {
            "type": "string",
            "description": "The description of one file, up to 2,000 characters counted as Bluesky counts them (graphemes)."
          }
        },
        "labels": {
          "type": "array",
          "maxItems": 2,
          "description": "Content warnings. At most one of `sexual` (Suggestive), `nudity` or `porn` (Adult),\nplus `graphic-media`. Only on posts with images or video. Bluesky leaves posts\nlabeled `sexual`, `porn` or `graphic-media` out of feeds for people who have not\nturned on adult content. Send `[]` for none.\n",
          "items": {
            "type": "string",
            "enum": [
              "sexual",
              "nudity",
              "porn",
              "graphic-media"
            ],
            "description": "One Bluesky self-label value."
          }
        }
      }
    },
    "PinterestSettings": {
      "type": "object",
      "description": "Per-account Pinterest options. Ignored for non-Pinterest accounts.",
      "required": [
        "boardId"
      ],
      "properties": {
        "boardId": {
          "type": "string",
          "pattern": "^\\d+$",
          "maxLength": 32,
          "description": "Numeric id of the board to pin to. Digits only. Anything else is rejected outright.\n"
        }
      }
    },
    "PlatformOverride": {
      "type": "object",
      "description": "Per-account content overrides. Anything omitted falls back to the post's own values, and\nan empty string is treated as \"no override\" rather than as blank content.\n",
      "properties": {
        "title": {
          "type": "string",
          "maxLength": 10000,
          "description": "Title to use for this account instead of the post's title."
        },
        "description": {
          "type": "string",
          "maxLength": 10000,
          "description": "Description to use for this account instead of the post's description."
        },
        "hashtags": {
          "type": "array",
          "maxItems": 30,
          "description": "Hashtags to use for this account instead of the post's hashtags.",
          "items": {
            "type": "string",
            "maxLength": 100,
            "description": "A single hashtag, without the `#`."
          }
        }
      }
    },
    "TikTokSettings": {
      "type": "object",
      "description": "Per-account TikTok options. Ignored for non-TikTok accounts.",
      "required": [
        "privacyLevel"
      ],
      "properties": {
        "deliveryMode": {
          "type": "string",
          "description": "Optional. `direct_post` publishes straight to the account's feed and is the only\naccepted value; any other value is rejected with a 400. Defaults to `direct_post`.\n",
          "enum": [
            "direct_post"
          ],
          "default": "direct_post"
        },
        "privacyLevel": {
          "type": [
            "string",
            "null"
          ],
          "maxLength": 64,
          "description": "Who can see the post, such as `PUBLIC_TO_EVERYONE` or `SELF_ONLY`. A null is\nrejected when the post is scheduled; leave the account out of `tiktokSettings`\nto publish to `PUBLIC_TO_EVERYONE`.\n"
        },
        "commercialContent": {
          "type": "boolean",
          "description": "Whether the video is disclosed as commercial content."
        },
        "brandOrganic": {
          "type": "boolean",
          "description": "Whether the disclosure marks the video as promoting your own brand."
        },
        "brandContent": {
          "type": "boolean",
          "description": "Whether the disclosure marks the video as a paid partnership."
        }
      }
    },
    "WordPressSettings": {
      "type": "object",
      "description": "How one WordPress account's copy of a blog post is created. Every field is optional.\nStored on that account's copy and returned on `GET /posts/{postId}`.\n",
      "properties": {
        "status": {
          "type": "string",
          "enum": [
            "publish",
            "draft"
          ],
          "description": "`publish` (the default when omitted) or `draft`, which creates a WordPress draft for\nthe site's author to review.\n"
        },
        "categories": {
          "type": "array",
          "description": "Category names. Each must already exist on the site; an unknown name fails with\n`400` listing the site's categories.\n",
          "items": {
            "type": "string",
            "description": "One category name."
          }
        },
        "tags": {
          "type": "array",
          "description": "Tag names. A tag the site does not have yet is created.",
          "items": {
            "type": "string",
            "description": "One tag name."
          }
        },
        "slug": {
          "type": "string",
          "maxLength": 200,
          "description": "The URL slug. Made from the title when omitted."
        },
        "excerpt": {
          "type": "string",
          "description": "Short summary shown in feeds and link previews."
        },
        "featuredImageAlt": {
          "type": "string",
          "description": "Alt text for the featured image, which is the post's first image."
        },
        "seo": {
          "type": "object",
          "description": "Yoast SEO fields. Only for an account whose site lets it write them; otherwise the\nrequest fails with `400`.\n",
          "properties": {
            "title": {
              "type": "string",
              "description": "SEO title shown in search results instead of the post title."
            },
            "description": {
              "type": "string",
              "description": "Meta description. Yoast prints none when this is omitted."
            },
            "focusKeyphrase": {
              "type": "string",
              "description": "Yoast focus keyphrase."
            }
          }
        }
      }
    }
  }
}