/*
* 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).
*
* The version of the OpenAPI document: 1.0.4
* Contact: support@zernio.com
* Generated by: https://openapi-generator.tech
*/
use crate::models;
use serde::{Deserialize, Serialize};
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct PlatformTarget {
/// Supported values: twitter, threads, instagram, youtube, facebook, linkedin, pinterest, reddit, tiktok, bluesky, googlebusiness, telegram
#[serde(rename = "platform", skip_serializing_if = "Option::is_none")]
pub platform: Option<String>,
#[serde(rename = "accountId", skip_serializing_if = "Option::is_none")]
pub account_id: Option<Box<models::PlatformTargetAccountId>>,
/// Platform-specific text override. When set, this content is used instead of the top-level post content for this platform. Useful for tailoring captions per platform (e.g. keeping tweets under 280 characters).
#[serde(rename = "customContent", skip_serializing_if = "Option::is_none")]
pub custom_content: Option<String>,
#[serde(rename = "customMedia", skip_serializing_if = "Option::is_none")]
pub custom_media: Option<Vec<models::MediaItem>>,
/// Optional per-platform scheduled time override (uses post.scheduledFor when omitted)
#[serde(rename = "scheduledFor", skip_serializing_if = "Option::is_none")]
pub scheduled_for: Option<String>,
/// The platform-specific options stored on this target, echoed back as they were sent. Typed per platform on the way in (see the *PlatformData schemas on the request body); free-form on the way out, because a response is not guaranteed to match exactly one of those variants and generated clients that pick a variant by structure reject the entire response when it doesn't. Zernio's internal publishing state (snapshots, container ids, publish stage) is never returned here, and the key is omitted rather than sent as an empty object.
#[serde(
rename = "platformSpecificData",
skip_serializing_if = "Option::is_none"
)]
pub platform_specific_data: Option<std::collections::HashMap<String, serde_json::Value>>,
/// Platform-specific status: pending, processing, uploading, published, failed, cancelled (removed from the platform via DELETE /v1/posts/{postId}/unpublish)
#[serde(rename = "status", skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
/// The native post ID on the platform (populated after successful publish)
#[serde(rename = "platformPostId", skip_serializing_if = "Option::is_none")]
pub platform_post_id: Option<String>,
/// Public URL of the published post. Included in the response for immediate posts; for scheduled posts, fetch via GET /v1/posts/{postId} after publish time. Empty when the platform confirmed the publish without returning an id a permalink can be built from (TikTok returns a publish id for some uploads); the TikTok reconcile cron backfills it later.
#[serde(
rename = "platformPostUrl",
default,
with = "::serde_with::rust::double_option",
skip_serializing_if = "Option::is_none"
)]
pub platform_post_url: Option<Option<String>>,
/// Timestamp when the post was published to this platform
#[serde(rename = "publishedAt", skip_serializing_if = "Option::is_none")]
pub published_at: Option<String>,
/// Set when a post that was successfully published later disappears from the platform (deleted on-platform or taken down by the platform). status stays \"published\" (it reflects the publish outcome); poll this field to detect post-publish removals. Absent while the post is live, and cleared if the post reappears. Detection runs with the analytics sync, so expect up to a few hours of lag.
#[serde(
rename = "removedFromPlatformAt",
default,
with = "::serde_with::rust::double_option",
skip_serializing_if = "Option::is_none"
)]
pub removed_from_platform_at: Option<Option<String>>,
/// Present and true only when this Instagram reel was launched as a Trial through Zernio (created with platformSpecificData.trialParams). Use it to segment trial reels in analytics. Note: Instagram's Graph API exposes no readable trial field, so this reflects creation-time intent only. It indicates the reel STARTED as a trial, not whether or when it graduated.
#[serde(rename = "isTrialReel", skip_serializing_if = "Option::is_none")]
pub is_trial_reel: Option<bool>,
/// Graduation strategy the trial reel was launched with. Present only when isTrialReel is true.
#[serde(
rename = "trialGraduationStrategy",
skip_serializing_if = "Option::is_none"
)]
pub trial_graduation_strategy: Option<TrialGraduationStrategy>,
/// Human-readable error message when status is failed. Contains platform-specific error details explaining why the publish failed.
#[serde(rename = "errorMessage", skip_serializing_if = "Option::is_none")]
pub error_message: Option<String>,
/// Error category for programmatic handling: auth_expired (token expired/revoked), user_content (wrong format/too long), user_abuse (rate limits/spam), account_issue (config problems), platform_rejected (policy violation), platform_error (5xx/maintenance), platform_rate_limit (platform throttling, retried automatically), quota_exhausted (a shared quota pool the integration draws on is empty, including our own capacity gate in front of one; not caused by your content or account, and safe to retry once the pool frees up), system_error (Zernio infra), unknown
#[serde(rename = "errorCategory", skip_serializing_if = "Option::is_none")]
pub error_category: Option<ErrorCategory>,
/// Who caused the error: user (fix content/reconnect), platform (outage/API change), system (Zernio issue, rare)
#[serde(rename = "errorSource", skip_serializing_if = "Option::is_none")]
pub error_source: Option<ErrorSource>,
}
impl PlatformTarget {
pub fn new() -> PlatformTarget {
PlatformTarget {
platform: None,
account_id: None,
custom_content: None,
custom_media: None,
scheduled_for: None,
platform_specific_data: None,
status: None,
platform_post_id: None,
platform_post_url: None,
published_at: None,
removed_from_platform_at: None,
is_trial_reel: None,
trial_graduation_strategy: None,
error_message: None,
error_category: None,
error_source: None,
}
}
}
/// Graduation strategy the trial reel was launched with. Present only when isTrialReel is true.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum TrialGraduationStrategy {
#[serde(rename = "MANUAL")]
Manual,
#[serde(rename = "SS_PERFORMANCE")]
SsPerformance,
}
impl Default for TrialGraduationStrategy {
fn default() -> TrialGraduationStrategy {
Self::Manual
}
}
/// Error category for programmatic handling: auth_expired (token expired/revoked), user_content (wrong format/too long), user_abuse (rate limits/spam), account_issue (config problems), platform_rejected (policy violation), platform_error (5xx/maintenance), platform_rate_limit (platform throttling, retried automatically), quota_exhausted (a shared quota pool the integration draws on is empty, including our own capacity gate in front of one; not caused by your content or account, and safe to retry once the pool frees up), system_error (Zernio infra), unknown
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum ErrorCategory {
#[serde(rename = "auth_expired")]
AuthExpired,
#[serde(rename = "user_content")]
UserContent,
#[serde(rename = "user_abuse")]
UserAbuse,
#[serde(rename = "account_issue")]
AccountIssue,
#[serde(rename = "platform_rejected")]
PlatformRejected,
#[serde(rename = "platform_error")]
PlatformError,
#[serde(rename = "platform_rate_limit")]
PlatformRateLimit,
#[serde(rename = "quota_exhausted")]
QuotaExhausted,
#[serde(rename = "system_error")]
SystemError,
#[serde(rename = "unknown")]
Unknown,
}
impl Default for ErrorCategory {
fn default() -> ErrorCategory {
Self::AuthExpired
}
}
/// Who caused the error: user (fix content/reconnect), platform (outage/API change), system (Zernio issue, rare)
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum ErrorSource {
#[serde(rename = "user")]
User,
#[serde(rename = "platform")]
Platform,
#[serde(rename = "system")]
System,
}
impl Default for ErrorSource {
fn default() -> ErrorSource {
Self::User
}
}