{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://raw.githubusercontent.com/api-evangelist/postonce/main/json-schema/postonce-workflow-schema.json",
  "title": "Workflow",
  "x-generated": "2026-10-14",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/_original/postonce-api-openapi.json#/components/schemas/Workflow",
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "profile_id": {
      "type": "string"
    },
    "source_account_id": {
      "type": "string"
    },
    "target_account_ids": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "settings": {
      "$ref": "#/$defs/WorkflowSettings"
    },
    "is_active": {
      "type": "boolean"
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time"
    },
    "name": {
      "type": "string"
    },
    "description": {
      "type": [
        "string",
        "null"
      ]
    },
    "future_content_enabled": {
      "type": "boolean"
    },
    "last_checked": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time"
    },
    "last_enabled_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time"
    }
  },
  "$defs": {
    "WorkflowSettings": {
      "type": "object",
      "properties": {
        "content_filters": {
          "type": "object",
          "properties": {
            "types": {
              "type": "object",
              "properties": {
                "text": {
                  "type": "boolean"
                },
                "image": {
                  "type": "boolean"
                },
                "quote": {
                  "type": "boolean"
                },
                "video": {
                  "type": "boolean"
                }
              }
            },
            "hashtags": {
              "type": "object",
              "properties": {
                "include": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "exclude": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "platform_settings": {
          "type": "object",
          "properties": {
            "tiktok": {
              "type": "object",
              "properties": {
                "keep_source_thumbnail": {
                  "type": "boolean",
                  "default": true,
                  "description": "When false, TikTok workflow posts do not prepend the source thumbnail as the first video frame."
                }
              }
            }
          }
        },
        "destination_publish_settings": {
          "type": "object",
          "additionalProperties": {
            "type": "object",
            "properties": {
              "minimum_interval_minutes": {
                "type": "integer",
                "minimum": 1
              },
              "caption_position": {
                "type": "string",
                "enum": [
                  "before",
                  "after"
                ],
                "description": "Placement of custom caption text. Defaults to after."
              },
              "remove_comment_dm_prompts": {
                "type": "boolean",
                "default": false,
                "description": "Remove comment/DM prompts from the original caption for this destination before applying custom before/after text. Supported on the same platforms as caption_ending."
              },
              "adapt_caption": {
                "type": "boolean",
                "default": false,
                "description": "Rewrite the caption for this destination with AI at publish time, after comment/DM prompt removal and before custom text. Links are always kept. If the rewrite fails, the original caption is published. Supported on the same platforms as caption_ending."
              },
              "adapt_caption_instructions": {
                "type": "string",
                "maxLength": 1000,
                "description": "Optional style instructions for the AI rewrite. When set, they replace the built-in guidance for the destination platform."
              },
              "caption_ending": {
                "type": "string",
                "maxLength": 2000,
                "description": "Optional custom caption text for this destination. Placement follows caption_position (after by default). Empty clears it. Supported for Instagram, Threads, X, Facebook, LinkedIn, Bluesky, Pinterest, YouTube and TikTok. Platform caption limits also apply."
              },
              "snapchat": {
                "type": "object",
                "required": [
                  "publish_targets"
                ],
                "properties": {
                  "publish_targets": {
                    "type": "array",
                    "minItems": 1,
                    "uniqueItems": true,
                    "items": {
                      "type": "string",
                      "enum": [
                        "spotlight",
                        "public_story"
                      ]
                    }
                  },
                  "locale": {
                    "type": "string",
                    "pattern": "^[a-z]{2}_[A-Z]{2}$",
                    "default": "en_US"
                  }
                }
              },
              "threads": {
                "type": "object",
                "properties": {
                  "caption_max_length": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 500,
                    "default": 500,
                    "description": "Maximum outgoing Threads caption length for this destination. Custom limits prefer whole words; 500 preserves default behavior."
                  }
                }
              },
              "instagram": {
                "type": "object",
                "anyOf": [
                  {
                    "required": [
                      "publish_as_trial_reel"
                    ]
                  },
                  {
                    "required": [
                      "remove_mentions"
                    ]
                  }
                ],
                "properties": {
                  "remove_mentions": {
                    "type": "boolean",
                    "default": false,
                    "description": "Remove @ from mentions in this Instagram destination's outgoing captions. Preserves usernames and email addresses."
                  },
                  "publish_as_trial_reel": {
                    "type": "boolean",
                    "default": false,
                    "description": "When true, eligible single-video Instagram Reels publish as Trial Reels for non-followers with manual graduation. Images and carousels publish normally."
                  }
                }
              },
              "reddit": {
                "type": "object",
                "required": [
                  "subreddit"
                ],
                "properties": {
                  "subreddit": {
                    "type": "string"
                  },
                  "post_type": {
                    "type": "string",
                    "enum": [
                      "auto",
                      "self",
                      "link"
                    ],
                    "default": "auto"
                  },
                  "flair_id": {
                    "type": "string"
                  },
                  "flair_text": {
                    "type": "string"
                  },
                  "nsfw": {
                    "type": "boolean",
                    "default": false
                  },
                  "spoiler": {
                    "type": "boolean",
                    "default": false
                  },
                  "send_replies": {
                    "type": "boolean",
                    "default": true
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}