late 0.0.1055

API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal. Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema). Request ids: responses carry an X-Request-Id header with the id we log the request under. Quote it when reporting a problem. A valid x-request-id you send is reused as that id.
Documentation
/*
 * Zernio API
 *
 * API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api  Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal.  Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema).  Request ids: responses carry an X-Request-Id header with the id we log the request under. Quote it when reporting a problem. A valid x-request-id you send is reused as that id.
 *
 * The version of the OpenAPI document: 1.104.0
 * Contact: support@zernio.com
 * Generated by: https://openapi-generator.tech
 */

use crate::models;
use serde::{Deserialize, Serialize};

/// TikTokPlatformData : Photo carousels up to 35 images. Video titles up to 2200 chars, photo titles truncated to 90 chars. privacyLevel must match creator_info options. Both camelCase and snake_case accepted.  Creator Inbox (draft mode): Set draft: true to send content to the TikTok Creator Inbox instead of publishing immediately. The creator receives an inbox notification and completes the post using TikTok's editing flow. This maps to TikTok's post_mode: \"MEDIA_UPLOAD\" internally.  Important: The field publish_type is NOT supported. Use draft: true for Creator Inbox flow.  Photo drafts use the /v2/post/publish/content/init/ endpoint with post_mode: \"MEDIA_UPLOAD\". Video drafts use the dedicated /v2/post/publish/inbox/video/init/ endpoint.  When draft: true, the video.upload scope is required. When draft is false or omitted (direct post), the video.publish scope is required. For Creator Inbox, TikTok app version must be 31.8 or higher.
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct TikTokPlatformData {
    /// When true, sends the post to the TikTok Creator Inbox as a draft instead of publishing immediately. The creator receives an inbox notification to complete posting via TikTok's editing flow. Maps to TikTok API post_mode: \"MEDIA_UPLOAD\" (photos) or the dedicated inbox endpoint (videos). When false or omitted, publishes directly via post_mode: \"DIRECT_POST\". Note: publish_type is not a supported field. Use this field instead.
    #[serde(rename = "draft", skip_serializing_if = "Option::is_none")]
    pub draft: Option<bool>,
    /// One of the values returned by the TikTok creator info API for the account. Accounts connected through the TikTok for Business app publish videos as public only: a non-public value on a video post is rejected at creation unless draft is true (photo posts keep every level).
    #[serde(rename = "privacyLevel", skip_serializing_if = "Option::is_none")]
    pub privacy_level: Option<String>,
    /// Allow comments on the post
    #[serde(rename = "allowComment", skip_serializing_if = "Option::is_none")]
    pub allow_comment: Option<bool>,
    /// Allow duets (required for video posts)
    #[serde(rename = "allowDuet", skip_serializing_if = "Option::is_none")]
    pub allow_duet: Option<bool>,
    /// Allow stitches (required for video posts)
    #[serde(rename = "allowStitch", skip_serializing_if = "Option::is_none")]
    pub allow_stitch: Option<bool>,
    /// Type of commercial content disclosure. Sufficient on its own: \"brand_organic\" (\"Your Brand\") implies isBrandOrganicPost and \"brand_content\" (\"Branded Content\", paid partnership) implies brandPartnerPromote, so you don't need to send the boolean flags separately. Branded content cannot be posted with privacyLevel SELF_ONLY.
    #[serde(
        rename = "commercialContentType",
        skip_serializing_if = "Option::is_none"
    )]
    pub commercial_content_type: Option<CommercialContentType>,
    /// Whether the post promotes a brand partner (branded content / paid partnership). Only needed to disclose BOTH types at once (set it alongside commercialContentType \"brand_organic\"), or to override the value implied by commercialContentType.
    #[serde(
        rename = "brandPartnerPromote",
        skip_serializing_if = "Option::is_none"
    )]
    pub brand_partner_promote: Option<bool>,
    /// Whether the post promotes the creator's own brand (brand organic). Only needed to disclose BOTH types at once (set it alongside commercialContentType \"brand_content\"), or to override the value implied by commercialContentType.
    #[serde(rename = "isBrandOrganicPost", skip_serializing_if = "Option::is_none")]
    pub is_brand_organic_post: Option<bool>,
    /// User has confirmed they previewed the content
    #[serde(
        rename = "contentPreviewConfirmed",
        skip_serializing_if = "Option::is_none"
    )]
    pub content_preview_confirmed: Option<bool>,
    /// User has given express consent for posting
    #[serde(
        rename = "expressConsentGiven",
        skip_serializing_if = "Option::is_none"
    )]
    pub express_consent_given: Option<bool>,
    /// Optional override. Defaults based on provided media items.
    #[serde(rename = "mediaType", skip_serializing_if = "Option::is_none")]
    pub media_type: Option<MediaType>,
    /// Optional for video posts. Timestamp in milliseconds to select which frame to use as thumbnail (defaults to 1000ms/1 second). Ignored when videoCoverImageUrl is provided.
    #[serde(
        rename = "videoCoverTimestampMs",
        skip_serializing_if = "Option::is_none"
    )]
    pub video_cover_timestamp_ms: Option<i32>,
    /// Optional for video posts. URL of a custom thumbnail image (JPG, PNG, or WebP, max 20MB). Any downloadable URL works: we rehost it ourselves. The image is stitched as a single frame at the start of the video to serve as the cover. Accounts connected through the TikTok for Business app hand it to TikTok as the cover instead, with no stitching, falling back to videoCoverTimestampMs without it. Overrides videoCoverTimestampMs when provided.
    #[serde(rename = "videoCoverImageUrl", skip_serializing_if = "Option::is_none")]
    pub video_cover_image_url: Option<String>,
    /// Optional for photo carousels. Index of image to use as cover, 0-based (defaults to 0/first image).
    #[serde(rename = "photoCoverIndex", skip_serializing_if = "Option::is_none")]
    pub photo_cover_index: Option<i32>,
    /// When true, TikTok may add recommended music (photos only). With the brand-organic or branded-content toggle on, TikTok allows Commercial Music Library tracks only, so this attaches nothing there; use musicSoundInfo instead.
    #[serde(rename = "autoAddMusic", skip_serializing_if = "Option::is_none")]
    pub auto_add_music: Option<bool>,
    #[serde(rename = "musicSoundInfo", skip_serializing_if = "Option::is_none")]
    pub music_sound_info: Option<Box<models::TikTokPlatformDataMusicSoundInfo>>,
    /// Volume of the video's own sound when a commercial track is attached (0 to 100). Requires musicSoundInfo. Video posts only.
    #[serde(
        rename = "videoOriginalSoundVolume",
        skip_serializing_if = "Option::is_none"
    )]
    pub video_original_sound_volume: Option<i32>,
    /// Set true to disclose AI-generated content. Accounts connected through the TikTok for Business app carry the disclosure on video posts only: the business photo endpoint has no AI disclosure field, so true on a direct photo post is rejected at creation rather than published undisclosed. Send draft true to publish such a photo post and set the disclosure in the TikTok app.
    #[serde(rename = "videoMadeWithAi", skip_serializing_if = "Option::is_none")]
    pub video_made_with_ai: Option<bool>,
    /// Location tag to attach, as the id of a result from GET /v1/accounts/{accountId}/tiktok/locations. Accounts connected through the TikTok for Business app and video posts only: a developer-app account rejects the post at publish time with a message that says so, and a direct photo post is rejected at creation since the business photo endpoint has no location field. Requires locationName. Ignored on drafts, where TikTok ignores every post_info field.
    #[serde(rename = "locationId", skip_serializing_if = "Option::is_none")]
    pub location_id: Option<String>,
    /// Display name of the location tag, as returned next to its id. Required with locationId; a locationId without it is rejected at creation.
    #[serde(rename = "locationName", skip_serializing_if = "Option::is_none")]
    pub location_name: Option<String>,
    /// Set true to publish the video as an \"Only show in ads\" post: it is kept off the profile and exists to be used as a Spark Ad. Accounts connected through the TikTok for Business app and video posts only, with the same rejections as locationId. Ignored on drafts.
    #[serde(rename = "isAdsOnly", skip_serializing_if = "Option::is_none")]
    pub is_ads_only: Option<bool>,
    /// Optional long-form caption for photo posts (max 4000 chars). Recommended when content exceeds 90 chars, as photo titles are auto-truncated. Falls back to the post content when omitted.
    #[serde(rename = "description", skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
}

impl TikTokPlatformData {
    /// Photo carousels up to 35 images. Video titles up to 2200 chars, photo titles truncated to 90 chars. privacyLevel must match creator_info options. Both camelCase and snake_case accepted.  Creator Inbox (draft mode): Set draft: true to send content to the TikTok Creator Inbox instead of publishing immediately. The creator receives an inbox notification and completes the post using TikTok's editing flow. This maps to TikTok's post_mode: \"MEDIA_UPLOAD\" internally.  Important: The field publish_type is NOT supported. Use draft: true for Creator Inbox flow.  Photo drafts use the /v2/post/publish/content/init/ endpoint with post_mode: \"MEDIA_UPLOAD\". Video drafts use the dedicated /v2/post/publish/inbox/video/init/ endpoint.  When draft: true, the video.upload scope is required. When draft is false or omitted (direct post), the video.publish scope is required. For Creator Inbox, TikTok app version must be 31.8 or higher.
    pub fn new() -> TikTokPlatformData {
        TikTokPlatformData {
            draft: None,
            privacy_level: None,
            allow_comment: None,
            allow_duet: None,
            allow_stitch: None,
            commercial_content_type: None,
            brand_partner_promote: None,
            is_brand_organic_post: None,
            content_preview_confirmed: None,
            express_consent_given: None,
            media_type: None,
            video_cover_timestamp_ms: None,
            video_cover_image_url: None,
            photo_cover_index: None,
            auto_add_music: None,
            music_sound_info: None,
            video_original_sound_volume: None,
            video_made_with_ai: None,
            location_id: None,
            location_name: None,
            is_ads_only: None,
            description: None,
        }
    }
}
/// Type of commercial content disclosure. Sufficient on its own: \"brand_organic\" (\"Your Brand\") implies isBrandOrganicPost and \"brand_content\" (\"Branded Content\", paid partnership) implies brandPartnerPromote, so you don't need to send the boolean flags separately. Branded content cannot be posted with privacyLevel SELF_ONLY.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum CommercialContentType {
    #[serde(rename = "none")]
    None,
    #[serde(rename = "brand_organic")]
    BrandOrganic,
    #[serde(rename = "brand_content")]
    BrandContent,
}

impl Default for CommercialContentType {
    fn default() -> CommercialContentType {
        Self::None
    }
}
/// Optional override. Defaults based on provided media items.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum MediaType {
    #[serde(rename = "video")]
    Video,
    #[serde(rename = "photo")]
    Photo,
}

impl Default for MediaType {
    fn default() -> MediaType {
        Self::Video
    }
}