/*
* 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.522.1
* Contact: support@zernio.com
* Generated by: https://openapi-generator.tech
*/
use reqwest;
use serde::{Deserialize, Serialize, de::Error as _};
use crate::{apis::ResponseContent, models};
use super::{Error, configuration, ContentType};
/// struct for typed errors of method [`on_account_ads_initial_sync_completed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAccountAdsInitialSyncCompletedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_account_ads_sync_failed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAccountAdsSyncFailedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_account_ads_sync_recovered`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAccountAdsSyncRecoveredError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_account_connected`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAccountConnectedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_account_disconnected`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAccountDisconnectedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_account_permissions_changed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAccountPermissionsChangedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_account_rate_limited`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAccountRateLimitedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_ad_account_status_changed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAdAccountStatusChangedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_ad_created`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAdCreatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_ad_delivery_issue`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAdDeliveryIssueError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_ad_review_approved`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAdReviewApprovedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_ad_review_rejected`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAdReviewRejectedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_ad_rule_triggered`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAdRuleTriggeredError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_ad_set_created`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAdSetCreatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_ad_set_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAdSetUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_ad_status_changed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAdStatusChangedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_ad_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAdUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_ad_video_processed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAdVideoProcessedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_analytics_synced`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAnalyticsSyncedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_api_changelog_published`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnApiChangelogPublishedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_automation_action_applied`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAutomationActionAppliedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_automation_action_failed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAutomationActionFailedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_automation_action_unknown`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAutomationActionUnknownError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_automation_alert_escalated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAutomationAlertEscalatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_automation_alert_opened`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAutomationAlertOpenedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_automation_alert_resolved`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAutomationAlertResolvedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_automation_check_completed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnAutomationCheckCompletedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_branded_calling_identity_action_required`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnBrandedCallingIdentityActionRequiredError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_branded_calling_identity_status_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnBrandedCallingIdentityStatusUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_branded_calling_number_status_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnBrandedCallingNumberStatusUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_calendar_event_created`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCalendarEventCreatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_calendar_event_deleted`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCalendarEventDeletedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_calendar_event_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCalendarEventUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_call_ended`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCallEndedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_call_failed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCallFailedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_call_permission_request`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCallPermissionRequestError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_call_received`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCallReceivedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_campaign_budget_depleted`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCampaignBudgetDepletedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_campaign_created`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCampaignCreatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_campaign_participant_joined`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCampaignParticipantJoinedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_campaign_participant_removed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCampaignParticipantRemovedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_campaign_participant_suspended`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCampaignParticipantSuspendedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_campaign_payout_failed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCampaignPayoutFailedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_campaign_payout_payable`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCampaignPayoutPayableError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_campaign_payout_settled`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCampaignPayoutSettledError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_campaign_submission_approved`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCampaignSubmissionApprovedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_campaign_submission_flagged`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCampaignSubmissionFlaggedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_campaign_submission_pending_review`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCampaignSubmissionPendingReviewError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_campaign_submission_received`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCampaignSubmissionReceivedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_campaign_submission_rejected`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCampaignSubmissionRejectedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_campaign_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCampaignUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_comment_received`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCommentReceivedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_commerce_order_created`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCommerceOrderCreatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_commerce_order_refunded`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCommerceOrderRefundedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_commerce_order_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCommerceOrderUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_commerce_product_created`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCommerceProductCreatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_commerce_product_deleted`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCommerceProductDeletedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_commerce_product_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCommerceProductUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_contact_deleted`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnContactDeletedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_contact_field_changed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnContactFieldChangedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_contact_tag_added`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnContactTagAddedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_contact_tag_removed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnContactTagRemovedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_contact_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnContactUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_conversation_control_changed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnConversationControlChangedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_conversation_started`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnConversationStartedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_creator_campaign_budget_exhausted`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCreatorCampaignBudgetExhaustedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_creator_campaign_closed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnCreatorCampaignClosedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_file_created`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnFileCreatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_file_deleted`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnFileDeletedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_file_picked`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnFilePickedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_file_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnFileUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_lead_received`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnLeadReceivedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_message_deleted`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnMessageDeletedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_message_delivered`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnMessageDeliveredError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_message_edited`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnMessageEditedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_message_failed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnMessageFailedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_message_played`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnMessagePlayedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_message_read`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnMessageReadError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_message_received`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnMessageReceivedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_message_sent`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnMessageSentError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_phone_number_stock_available`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnPhoneNumberStockAvailableError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_post_authenticity_changed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnPostAuthenticityChangedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_post_cancelled`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnPostCancelledError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_post_external_created`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnPostExternalCreatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_post_external_deleted`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnPostExternalDeletedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_post_external_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnPostExternalUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_post_failed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnPostFailedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_post_partial`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnPostPartialError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_post_platform_deleted`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnPostPlatformDeletedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_post_platform_failed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnPostPlatformFailedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_post_platform_published`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnPostPlatformPublishedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_post_published`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnPostPublishedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_post_recycled`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnPostRecycledError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_post_scheduled`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnPostScheduledError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_post_tik_tok_url_resolved`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnPostTikTokUrlResolvedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_post_tracking_completed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnPostTrackingCompletedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_rcs_agent_status_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnRcsAgentStatusUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_reaction_received`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnReactionReceivedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_referral_received`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnReferralReceivedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_review_deleted`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnReviewDeletedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_review_new`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnReviewNewError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_review_restored`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnReviewRestoredError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_review_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnReviewUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_sequence_enrolled`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnSequenceEnrolledError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_sequence_exited`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnSequenceExitedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_sms_registration_action_required`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnSmsRegistrationActionRequiredError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_sms_registration_status_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnSmsRegistrationStatusUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_support_run_completed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnSupportRunCompletedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_support_run_failed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnSupportRunFailedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_verification_approved`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnVerificationApprovedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_verification_failed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnVerificationFailedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_webhook_test`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWebhookTestError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_whats_app_account_alert_received`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWhatsAppAccountAlertReceivedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_whats_app_account_name_status_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWhatsAppAccountNameStatusUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_whats_app_account_quality_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWhatsAppAccountQualityUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_whats_app_account_status_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWhatsAppAccountStatusUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_whats_app_automatic_event`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWhatsAppAutomaticEventError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_whats_app_contact_identity_changed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWhatsAppContactIdentityChangedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_whats_app_number_action_required`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWhatsAppNumberActionRequiredError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_whats_app_number_activated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWhatsAppNumberActivatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_whats_app_number_declined`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWhatsAppNumberDeclinedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_whats_app_number_kyc_submitted`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWhatsAppNumberKycSubmittedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_whats_app_number_reactivated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWhatsAppNumberReactivatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_whats_app_number_released`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWhatsAppNumberReleasedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_whats_app_number_suspended`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWhatsAppNumberSuspendedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_whats_app_number_verification_required`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWhatsAppNumberVerificationRequiredError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_whats_app_template_category_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWhatsAppTemplateCategoryUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_whats_app_template_status_updated`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWhatsAppTemplateStatusUpdatedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_workflow_run_completed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWorkflowRunCompletedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_workflow_run_failed`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWorkflowRunFailedError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`on_workflow_run_started`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnWorkflowRunStartedError {
UnknownValue(serde_json::Value),
}
/// The initial sync, ad-account discovery plus a 90-day ad backfill, completed for an ads-enabled account. ### When it fires Fires once per ads-enabled account. `sync` reports whether the backfill succeeded fully or partially, and how many ads were synced versus failed. ### Scoped connects When scoping was applied at connect time, `account.platformAdAccountId` echoes the chosen ad account when the scope is exactly one. `account.platformAdAccountIds` lists every `act_*` synced. ### On failure When `sync.status` is `\"failure\"`, the payload adds `sync.error` (raw platform error, about 2 KB), `sync.errorCode` and `sync.errorSubcode` when parseable, and `sync.errorCategory`. ### Error categories `sync.errorCategory` is `token_invalid`, `permission_denied`, `no_ad_accounts`, `rate_limited`, `discovery_failed` or `unknown`. New values may be added; existing ones are stable. ### Retrying Reconnecting re-queues the backfill and the event fires again. It fixes `token_invalid`, `permission_denied` and `rate_limited`; `no_ad_accounts` needs an ad account on the grant first. ### When a retry is skipped Zernio skips the re-queue only when a backfill already completed with at least one ad, or one started less than 20 minutes ago.
pub async fn on_account_ads_initial_sync_completed(configuration: &configuration::Configuration, webhook_payload_account_ads_initial_sync_completed: models::WebhookPayloadAccountAdsInitialSyncCompleted) -> Result<(), Error<OnAccountAdsInitialSyncCompletedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_account_ads_initial_sync_completed = webhook_payload_account_ads_initial_sync_completed;
let uri_str = format!("{}/account.ads.initial_sync_completed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_account_ads_initial_sync_completed);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAccountAdsInitialSyncCompletedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An ad account's ads stopped syncing: no success for 24 hours, or every live ad at the retry cap. ### When it fires An hourly check covers every ad account with live ads on a connected account, on any ads platform. Fires once per ad account until `account.ads.sync_recovered`. ### Stale metrics Metrics for the ad account are stale in between. Use this signal to flag the numbers in your UI rather than to poll. ### Payload notes `adAccount.platformAdAccountId` names the ad account (`act_*` on Meta). `account.accountId` names its connection, so one connection with several ad accounts reports each separately. ### Sync fields `sync.lastSuccessfulSyncAt` is the last good sync and `sync.failureCount` the consecutive failed attempts. ### Error categories Branch on `sync.errorCategory`: `ad_account_not_listed` (access removed or platform change; check permissions, reconnect), `sync_error` (see `sync.error`) or `stale` (no error recorded; retries usually clear it). New values may be added. ### When it does not fire A disconnected connection gets `account.disconnected` instead, and no recovery event follows. An ad account that never synced successfully, or whose last good sync is over 3 days old, is not announced.
pub async fn on_account_ads_sync_failed(configuration: &configuration::Configuration, webhook_payload_account_ads_sync_failed: models::WebhookPayloadAccountAdsSyncFailed) -> Result<(), Error<OnAccountAdsSyncFailedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_account_ads_sync_failed = webhook_payload_account_ads_sync_failed;
let uri_str = format!("{}/account.ads.sync_failed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_account_ads_sync_failed);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAccountAdsSyncFailedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An ad account previously reported by `account.ads.sync_failed` synced successfully again. ### When it fires Fires once when a sync succeeds again, found by an hourly check. ### Payload notes `sync.failingSince` is the last successful sync before the failure started.
pub async fn on_account_ads_sync_recovered(configuration: &configuration::Configuration, webhook_payload_account_ads_sync_recovered: models::WebhookPayloadAccountAdsSyncRecovered) -> Result<(), Error<OnAccountAdsSyncRecoveredError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_account_ads_sync_recovered = webhook_payload_account_ads_sync_recovered;
let uri_str = format!("{}/account.ads.sync_recovered", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_account_ads_sync_recovered);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAccountAdsSyncRecoveredError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An account was connected to a profile, through OAuth or credentials. ### Repeat events Reconnecting an account you already hold fires it again with the same `accountId`, since the connect flow upserts per profile and platform. Key your upsert on `accountId`.
pub async fn on_account_connected(configuration: &configuration::Configuration, webhook_payload_account_connected: models::WebhookPayloadAccountConnected) -> Result<(), Error<OnAccountConnectedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_account_connected = webhook_payload_account_connected;
let uri_str = format!("{}/account.connected", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_account_connected);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAccountConnectedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A connected account stopped working or was removed. ### Intentional Removed on purpose, such as `DELETE /v1/accounts/{id}` or a switch to the Free plan. Kept 1 hour (`gracePeriodEndsAt`), then deleted with no further event. Reconnecting within the hour restores the same `accountId`. ### Unintentional The connection broke (token expired or revoked, access lost). The account stays inactive until reconnected, keeping its `accountId`. Removing it instead sends a second event with `intentional`. ### Immediate paths An API removal emits at once with `disconnectionType: \"intentional\"`. A phone-side WhatsApp disconnect emits within seconds of Meta's notification, with `unintentional`. ### WhatsApp reason `reason` carries Meta's explanation. Deliberate: `BUSINESS_DOWNGRADE`, `CHANGE_NUMBER`, `USER_RE_REGISTERED`. Idle number dropped by Meta: `PRIMARY_INACTIVITY` after about 14 days, `COMPANION_INACTIVITY` after about 30. ### Expired or revoked grants A publish or analytics sync getting a definitive auth error deactivates the account. Publish tries a token refresh first, so the event means the refresh failed too. `reason` carries the platform's message. ### Reconnection flags A dead token on an ads or blog call flags the account, and the posting account sharing its token (`needsReconnection: true`). Each flagged account emits once; a later deactivation emits again, then not until reconnected. ### Lead forms while disconnected While a Facebook Page is flagged or deactivated, `GET /v1/ads/lead-forms/{formId}/leads` answers `409` with `code: \"account_disconnected\"`. ### Reconciliation Anything else (a number deleted in WhatsApp Manager, a channel Meta silently stops serving) is caught by periodic reconciliation, not a notification. It lags minutes to about a day. ### Do not rely on its absence Meta's notifications are best-effort. For WhatsApp, poll `GET /v1/whatsapp/number-info` or account health, which runs a live Meta link probe. ### Subscribing A webhook only receives the events it lists, so add `account.disconnected` explicitly.
pub async fn on_account_disconnected(configuration: &configuration::Configuration, webhook_payload_account_disconnected: models::WebhookPayloadAccountDisconnected) -> Result<(), Error<OnAccountDisconnectedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_account_disconnected = webhook_payload_account_disconnected;
let uri_str = format!("{}/account.disconnected", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_account_disconnected);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAccountDisconnectedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A publish on an account connected through your own OAuth app failed for a missing permission. ### Behaviour The account stays connected and its token still works. `account.missingScopeAreas` accumulates the affected areas, today `posting`. Each area sends one event, however many posts fail afterwards. ### When it does not fire Accounts not connected through your own OAuth app.
pub async fn on_account_permissions_changed(configuration: &configuration::Configuration, webhook_payload_account_permissions_changed: models::WebhookPayloadAccountPermissionsChanged) -> Result<(), Error<OnAccountPermissionsChangedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_account_permissions_changed = webhook_payload_account_permissions_changed;
let uri_str = format!("{}/account.permissions_changed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_account_permissions_changed);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAccountPermissionsChangedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A Google or Microsoft mailbox was paused after sending one body to over 50 recipients in an hour. ### Payload notes `account.reason` says why and `account.resetsAt` says when sending resumes. Sends answer 429 until then. A later trigger can also start a cooldown.
pub async fn on_account_rate_limited(configuration: &configuration::Configuration, webhook_payload_account_rate_limited: models::WebhookPayloadAccountRateLimited) -> Result<(), Error<OnAccountRateLimitedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_account_rate_limited = webhook_payload_account_rate_limited;
let uri_str = format!("{}/account.rate_limited", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_account_rate_limited);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAccountRateLimitedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An ad account Zernio already tracked became `active`, `restricted`, `disabled` or `closed`. ### When it fires Fires when ad account discovery sees a tracked ad account change status, at most once per account per 24 hours. Covers Meta, Google, TikTok and X. ### Status values `restricted` needs something settled first (unpaid Meta balance, risk review, TikTok limit or pending verification, X review). `disabled` means the platform disabled or rejected it; `closed` means closed or pending closure. ### Payload notes `status.current` and `status.previous` use one vocabulary on every network. `status.raw` is the platform's own value, for example Meta's `account_status` code `2`. ### When it does not fire An account seen for the first time, an account Zernio has not seen in the last 48 hours, or a platform status Zernio does not recognize.
pub async fn on_ad_account_status_changed(configuration: &configuration::Configuration, webhook_payload_ad_account_status_changed: models::WebhookPayloadAdAccountStatusChanged) -> Result<(), Error<OnAdAccountStatusChangedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_ad_account_status_changed = webhook_payload_ad_account_status_changed;
let uri_str = format!("{}/ad_account.status_changed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_ad_account_status_changed);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAdAccountStatusChangedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An ad was created through Zernio (`source: \"zernio\"`) or detected by the sync (`source: \"platform\"`). ### When it fires Fires once the ad's campaign and ad set are recorded. A detected ad arrives up to one sync interval late; Meta ads entering review usually arrive within minutes. ### When it does not fire History loaded when an account connects, and ads created more than 7 days ago, are never announced.
pub async fn on_ad_created(configuration: &configuration::Configuration, webhook_payload_ad_created: models::WebhookPayloadAdCreated) -> Result<(), Error<OnAdCreatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_ad_created = webhook_payload_ad_created;
let uri_str = format!("{}/ad.created", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_ad_created);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAdCreatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An ad Zernio already tracked moved into the platform's error state and stopped delivering. ### What triggers it Meta `WITH_ISSUES` (payment, policy or account problems), TikTok account punishment or missing balance, or any platform status Zernio does not recognize yet (check `issue.raw`). ### When it fires Fires at most once per ad per 24 hours. Ads seen for the first time by a sync never fire it. ### Payload notes `issue.raw` is the platform's status string. On Meta, `issue.reasons` carries Meta's messages for the campaign; other networks send none, so it is empty. ### Platform notes On Meta the same problem can also arrive as `ad.status_changed` with `WITH_ISSUES`, straight from Meta's webhook and usually sooner. Pick one of the two to act on.
pub async fn on_ad_delivery_issue(configuration: &configuration::Configuration, webhook_payload_ad_delivery_issue: models::WebhookPayloadAdDeliveryIssue) -> Result<(), Error<OnAdDeliveryIssueError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_ad_delivery_issue = webhook_payload_ad_delivery_issue;
let uri_str = format!("{}/ad.delivery_issue", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_ad_delivery_issue);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAdDeliveryIssueError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An ad Zernio already tracked passed platform review, or a rejected ad was approved on appeal. ### When it fires Fires within one sync cycle of the platform's decision, not instantly; on Meta the review poll usually reports sooner. Each outcome is delivered at most once per ad per 24 hours. ### When it does not fire Ads seen for the first time by a sync never fire it, including history loaded at connect. On Meta, Google, TikTok and Reddit an ad that leaves review while paused sends no `approved`. ### Platform notes Covers every ad network Zernio syncs, with one payload shape. On X, Pinterest and LinkedIn the review is read apart from delivery status, so an ad leaving review while paused still sends `approved`. ### Payload notes `review.raw` is the platform's own status string. `adObject.adId` is the Zernio ad id, ready for `GET /v1/ads/{adId}`. Deduplicate on the event `id`.
pub async fn on_ad_review_approved(configuration: &configuration::Configuration, webhook_payload_ad_review: models::WebhookPayloadAdReview) -> Result<(), Error<OnAdReviewApprovedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_ad_review = webhook_payload_ad_review;
let uri_str = format!("{}/ad.review.approved", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_ad_review);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAdReviewApprovedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// The platform rejected an ad Zernio already tracked; `review.reasons` carries its reason when it gives one. ### When it fires Fires within one sync cycle of the platform's decision, not instantly; on Meta the review poll usually reports sooner. Each outcome is delivered at most once per ad per 24 hours. ### When it does not fire Ads seen for the first time by a sync never fire it, including history loaded at connect. ### Platform notes Covers every ad network Zernio syncs. Pinterest, LinkedIn and Reddit send their own reasons, X sends none, and most other networks return a generic message. ### Payload notes `review.raw` is the platform's own status string. Show `review.reasons` rather than branching on it. `adObject.adId` is the Zernio ad id. Deduplicate on the event `id`.
pub async fn on_ad_review_rejected(configuration: &configuration::Configuration, webhook_payload_ad_review: models::WebhookPayloadAdReview) -> Result<(), Error<OnAdReviewRejectedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_ad_review = webhook_payload_ad_review;
let uri_str = format!("{}/ad.review.rejected", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_ad_review);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAdReviewRejectedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A scheduled run of an ad rule with a `notify` action found campaigns or ad sets meeting every condition. ### When it fires Each object is announced at most once per rule cooldown. A run where every object is still in cooldown sends nothing. ### Failed actions An object whose action `failed` gets no cooldown, so the next run retries it and reports it again. ### Payload notes `objects` lists only the objects the run acted on. `objects[].conditions` repeats every condition of the rule with `actual`, the value the object reached. ### Actions `objects[].actions` says what the rule did: `done`, `skipped` (with a `reason` such as `already_paused` or `at_limit`) or `failed`. On `adjust_budget` it carries `previousDailyBudget` and `newDailyBudget`; empty on a notify-only rule. ### Run context `run.today` and `run.timezone` give the ad account's calendar date the windows used. `run.timezoneAssumed` is `true` when UTC was assumed. `run.currency` is the currency of money metrics, or `null` when unknown.
pub async fn on_ad_rule_triggered(configuration: &configuration::Configuration, webhook_payload_ad_rule_triggered: models::WebhookPayloadAdRuleTriggered) -> Result<(), Error<OnAdRuleTriggeredError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_ad_rule_triggered = webhook_payload_ad_rule_triggered;
let uri_str = format!("{}/ad_rule.triggered", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_ad_rule_triggered);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAdRuleTriggeredError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An ad set was created through Zernio (`source: \"zernio\"`) or detected by the sync (`source: \"platform\"`). ### When it fires Fires once the ad set row is recorded, so `GET /v1/ads/ad-sets/{adSetId}` finds it. A detected ad set arrives up to one sync interval late. ### Payload notes `adObject.campaign` is the campaign the ad set belongs to, or null when the platform has none. ### When it does not fire History loaded when an account connects, and ad sets created more than 7 days ago, are never announced.
pub async fn on_ad_set_created(configuration: &configuration::Configuration, webhook_payload_ad_set_created: models::WebhookPayloadAdSetCreated) -> Result<(), Error<OnAdSetCreatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_ad_set_created = webhook_payload_ad_set_created;
let uri_str = format!("{}/ad_set.created", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_ad_set_created);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAdSetCreatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An ad set was edited through Zernio (`source: \"zernio\"`), or outside Zernio and detected by the sync (`source: \"platform\"`). ### When it fires Fires after the platform and Zernio both accepted the edit. Outside edits arrive up to one sync interval late, and only to the user whose sync saw them. ### Deduplication Events are not deduplicated, so every edit is announced. Use the event `id` to drop repeats. ### Payload notes `changes` lists the edited fields: `name`, `status` (the ad set's own on/off switch), `budget`, `bid`, `schedule`, `targeting` or `settings`. Ignore unknown values. It never carries old or new values, so read the ad set. ### What the sync detects From the sync, `changes` covers only `name` and `status`. Status is not detected on Reddit. ### When it does not fire History loaded when an account connects is never announced. Budget and targeting edits made through `PUT /v1/ads/{adId}` arrive as `ad.updated`.
pub async fn on_ad_set_updated(configuration: &configuration::Configuration, webhook_payload_ad_set_updated: models::WebhookPayloadAdSetUpdated) -> Result<(), Error<OnAdSetUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_ad_set_updated = webhook_payload_ad_set_updated;
let uri_str = format!("{}/ad_set.updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_ad_set_updated);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAdSetUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A campaign, ad set or ad on a connected Meta ad account (`metaads`) changed status. ### Sources Two Meta `ad_account` fields feed it: `in_process_ad_objects` (finished processing, `status.raw` is Meta's `status_name`) and `with_issues_ad_objects` (`status.raw` is `WITH_ISSUES`, `error` filled from Meta). ### Payload notes `adObject.level` is `CAMPAIGN`, `AD_SET` or `AD`; creative-level events are not forwarded. Branch on `status.raw`. Use `error.code` as the stable discriminator, since `error.summary` and `error.message` are localized to the owner's Meta locale. ### The error block `error` is present on most `WITH_ISSUES` events but can be absent, and never appears on any other status. Null-check it before reading `error.code`. ### Fan-out Matching is keyed on `adObject.platformAdAccountId`. When several connected `metaads` accounts point at the same Meta ad account, each receives its own delivery.
pub async fn on_ad_status_changed(configuration: &configuration::Configuration, webhook_payload_ad_status_changed: models::WebhookPayloadAdStatusChanged) -> Result<(), Error<OnAdStatusChangedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_ad_status_changed = webhook_payload_ad_status_changed;
let uri_str = format!("{}/ad.status_changed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_ad_status_changed);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAdStatusChangedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An ad was edited through Zernio (`source: \"zernio\"`), or outside Zernio and detected by the sync (`source: \"platform\"`). ### When it fires Fires once, to the owner of the edited ad. Outside edits arrive up to one sync interval late. Every edit is announced, so use the event `id` to drop repeats. ### Payload notes `changes` lists the edited fields: `name`, `status` (the ad's own on/off switch), `budget`, `targeting` or `creative`. Ignore unknown values; new ones can be added. ### Reading the change The event never carries old or new values, so read the ad. `platformId` can change when a LinkedIn creative is replaced, while `adId` stays stable. ### When it does not fire From the sync, `changes` covers only `name` and `status`. Budget, bid, schedule and targeting edits made outside Zernio, tracking tag edits and history loaded at connect are not announced. Ad rule changes arrive as `ad_rule.triggered`.
pub async fn on_ad_updated(configuration: &configuration::Configuration, webhook_payload_ad_updated: models::WebhookPayloadAdUpdated) -> Result<(), Error<OnAdUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_ad_updated = webhook_payload_ad_updated;
let uri_str = format!("{}/ad.updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_ad_updated);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAdUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// Meta finished processing a video uploaded with `async: true` on `POST /v1/ads/videos`. ### Payload notes `video.status` is `ready` (reference it as `video.id` on the create endpoints) or `error`, with `video.error` carrying the reason. ### When it fires Fires once per upload, when the video leaves `processing`. Zernio polls every 10 seconds for about 13 minutes; after that no event is sent, so read `GET /v1/ads/videos/{videoId}` for long videos.
pub async fn on_ad_video_processed(configuration: &configuration::Configuration, webhook_payload_ad_video_processed: models::WebhookPayloadAdVideoProcessed) -> Result<(), Error<OnAdVideoProcessedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_ad_video_processed = webhook_payload_ad_video_processed;
let uri_str = format!("{}/ad.video.processed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_ad_video_processed);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAdVideoProcessedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// One connected account's analytics sync cycle completed successfully. ### Payload notes It is a trigger: no metrics and no cursor. On receipt, call `GET /v1/analytics/delta` with your own last `nextCursor` to read what changed across every account. ### When it fires Per account, per successful sync cycle, roughly hourly. It does not fire for a failed or skipped cycle, an inactive or disconnected account, or a platform without analytics sync. ### Empty page The feed is a materialized view, so an immediate read can return an empty `data` array. Re-poll with the same cursor. Advancing on an empty page can lose changes permanently. ### Use a dedicated endpoint Volume is about one event per account per hour. The consecutive-failure count is shared by every event on an endpoint, so an outage here can disable it and silence events like `post.published`.
pub async fn on_analytics_synced(configuration: &configuration::Configuration, webhook_payload_analytics_synced: models::WebhookPayloadAnalyticsSynced) -> Result<(), Error<OnAnalyticsSyncedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_analytics_synced = webhook_payload_analytics_synced;
let uri_str = format!("{}/analytics.synced", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_analytics_synced);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAnalyticsSyncedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An entry was published to the API changelog when a change to the OpenAPI spec went live. ### Who receives it It belongs to no profile or account. Every active endpoint subscribed to it receives it; endpoints scoped with `profileIds` or `accountIds` do not. One subscription per integration is enough. ### Payload notes `entry.type`, `entry.message` (the announcement), `entry.url`, `entry.specVersion`, `entry.impact` (`action_required`, `additive` or `none`) and `entry.changes` (the spec diff as data). ### How to act Automate on `impact`, `changes` and `type`; read `message` for the reason. `GET /v1/changelog` lists entries newest first, to back-fill after downtime.
pub async fn on_api_changelog_published(configuration: &configuration::Configuration, webhook_payload_api_changelog_published: models::WebhookPayloadApiChangelogPublished) -> Result<(), Error<OnApiChangelogPublishedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_api_changelog_published = webhook_payload_api_changelog_published;
let uri_str = format!("{}/api.changelog.published", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_api_changelog_published);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnApiChangelogPublishedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An automation changed something, such as an ad set paused or a budget raised. ### Payload notes `previous` and `target` carry the value before and the value set. Each action sends one event; dedupe on `id`, which stays the same if the event is sent again.
pub async fn on_automation_action_applied(configuration: &configuration::Configuration, webhook_payload_automation_action: models::WebhookPayloadAutomationAction) -> Result<(), Error<OnAutomationActionAppliedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_automation_action = webhook_payload_automation_action;
let uri_str = format!("{}/automation.action.applied", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_automation_action);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAutomationActionAppliedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An automation change failed or was refused; `reason` says why. ### Skipped changes A change refused before any platform call has `status: skipped`, for example no live ads or a budget at its limit.
pub async fn on_automation_action_failed(configuration: &configuration::Configuration, webhook_payload_automation_action: models::WebhookPayloadAutomationAction) -> Result<(), Error<OnAutomationActionFailedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_automation_action = webhook_payload_automation_action;
let uri_str = format!("{}/automation.action.failed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_automation_action);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAutomationActionFailedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// The platform did not answer, so it is unknown whether the automation's change happened. ### What happens next The next check reads the object back and sends `applied` or `failed`.
pub async fn on_automation_action_unknown(configuration: &configuration::Configuration, webhook_payload_automation_action: models::WebhookPayloadAutomationAction) -> Result<(), Error<OnAutomationActionUnknownError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_automation_action = webhook_payload_automation_action;
let uri_str = format!("{}/automation.action.unknown", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_automation_action);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAutomationActionUnknownError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An open alert's `critical` conditions held. ### When it fires Sent once per episode.
pub async fn on_automation_alert_escalated(configuration: &configuration::Configuration, webhook_payload_automation_alert: models::WebhookPayloadAutomationAlert) -> Result<(), Error<OnAutomationAlertEscalatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_automation_alert = webhook_payload_automation_alert;
let uri_str = format!("{}/automation.alert.escalated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_automation_alert);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAutomationAlertEscalatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An object matched the rule's conditions for `confirmChecks` runs in a row and its action was recorded. ### When it fires Sent once per episode.
pub async fn on_automation_alert_opened(configuration: &configuration::Configuration, webhook_payload_automation_alert: models::WebhookPayloadAutomationAlert) -> Result<(), Error<OnAutomationAlertOpenedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_automation_alert = webhook_payload_automation_alert;
let uri_str = format!("{}/automation.alert.opened", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_automation_alert);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAutomationAlertOpenedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An open alert ended; `reason` says which way. ### Reasons Its conditions cleared, a pause or reactivation applied, the rule changed, or nothing checked the object for 7 days.
pub async fn on_automation_alert_resolved(configuration: &configuration::Configuration, webhook_payload_automation_alert: models::WebhookPayloadAutomationAlert) -> Result<(), Error<OnAutomationAlertResolvedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_automation_alert = webhook_payload_automation_alert;
let uri_str = format!("{}/automation.alert.resolved", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_automation_alert);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAutomationAlertResolvedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// One scheduled check of an automation finished, including checks where nothing matched. ### Payload notes `automation.kind` names the product: `ad_rule` today, more as other automations move onto the same engine.
pub async fn on_automation_check_completed(configuration: &configuration::Configuration, webhook_payload_automation_check_completed: models::WebhookPayloadAutomationCheckCompleted) -> Result<(), Error<OnAutomationCheckCompletedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_automation_check_completed = webhook_payload_automation_check_completed;
let uri_str = format!("{}/automation.check.completed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_automation_check_completed);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnAutomationCheckCompletedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A Branded Calling caller identity is waiting on you; `reason` says what. ### When it fires Every `action_required` is paired with a `status_updated`. ### Reasons - `changes_requested`: answer the review with `PATCH`. - `email_code`: confirm the code the carrier emailed the authorizer. - `rejected`: fix and `PATCH`. - `expired`: resubmit. ### Infringement claim `infringement_claim`: a third party filed a trademark or impersonation claim and the carrier suspended the identity. Calls show a plain number and the monthly fee pauses until it is resolved. Reply to our email with evidence that the name and logo are yours. If the claim is upheld, the identity is rejected for good.
pub async fn on_branded_calling_identity_action_required(configuration: &configuration::Configuration, on_branded_calling_identity_action_required_request: models::OnBrandedCallingIdentityActionRequiredRequest) -> Result<(), Error<OnBrandedCallingIdentityActionRequiredError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_on_branded_calling_identity_action_required_request = on_branded_calling_identity_action_required_request;
let uri_str = format!("{}/branded_calling.identity.action_required", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_on_branded_calling_identity_action_required_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnBrandedCallingIdentityActionRequiredError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A Branded Calling caller identity changed status. ### When it fires Fires once per transition of the identity's `status`, the value `GET /v1/branded-calling/identities/{id}` returns. Never on a re-check that found nothing new. ### Statuses `requested`, `changes_requested`, `rejected` (`reason` says why), `pending_email_verification`, `in_review`, `verified` (live for a year, attach numbers), `suspended` (infringement claim open), `expired`, `permanently_rejected`.
pub async fn on_branded_calling_identity_status_updated(configuration: &configuration::Configuration, on_branded_calling_identity_status_updated_request: models::OnBrandedCallingIdentityStatusUpdatedRequest) -> Result<(), Error<OnBrandedCallingIdentityStatusUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_on_branded_calling_identity_status_updated_request = on_branded_calling_identity_status_updated_request;
let uri_str = format!("{}/branded_calling.identity.status_updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_on_branded_calling_identity_status_updated_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnBrandedCallingIdentityStatusUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A number attached to a Branded Calling identity changed vetting status. ### When it fires Only starts once the identity is `verified` and you attached numbers. A batch is vetted as a unit; each number reports its own status. ### Statuses `submitted`, `in_review`, `verified` (calls from it show the identity), `unsuccessful` (refused; detach and re-add to retry), `suspended`, `expired`, `permanently_rejected` (can never be branded again).
pub async fn on_branded_calling_number_status_updated(configuration: &configuration::Configuration, on_branded_calling_number_status_updated_request: models::OnBrandedCallingNumberStatusUpdatedRequest) -> Result<(), Error<OnBrandedCallingNumberStatusUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_on_branded_calling_number_status_updated_request = on_branded_calling_number_status_updated_request;
let uri_str = format!("{}/branded_calling.number.status_updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_on_branded_calling_number_status_updated_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnBrandedCallingNumberStatusUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An event was added to the primary calendar of a connected mailbox, by the user, an invitation or the API. ### Platform notes On Microsoft the change is pushed seconds after it happens.
pub async fn on_calendar_event_created(configuration: &configuration::Configuration, webhook_payload_calendar_event: models::WebhookPayloadCalendarEvent) -> Result<(), Error<OnCalendarEventCreatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_calendar_event = webhook_payload_calendar_event;
let uri_str = format!("{}/calendar.event.created", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_calendar_event);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCalendarEventCreatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An event was deleted from the primary calendar. ### Platform notes On Google, a cancelled event counts as deleted.
pub async fn on_calendar_event_deleted(configuration: &configuration::Configuration, webhook_payload_calendar_event: models::WebhookPayloadCalendarEvent) -> Result<(), Error<OnCalendarEventDeletedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_calendar_event = webhook_payload_calendar_event;
let uri_str = format!("{}/calendar.event.deleted", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_calendar_event);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCalendarEventDeletedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An event on the primary calendar changed: its time, details or participants' answers.
pub async fn on_calendar_event_updated(configuration: &configuration::Configuration, webhook_payload_calendar_event: models::WebhookPayloadCalendarEvent) -> Result<(), Error<OnCalendarEventUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_calendar_event = webhook_payload_calendar_event;
let uri_str = format!("{}/calendar.event.updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_calendar_event);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCalendarEventUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A phone or WhatsApp call ended; carries duration, end reason and a zero-markup cost breakdown. ### Payload notes `durationSeconds`; `endReason` is `hangup`, `no_answer`, `rejected` or `error`; `call.billing` holds Meta cost, Telnyx cost, recording surcharge and total. Costs are pass-through, with no margin. ### When it fires Unanswered, busy and rejected calls end here too. Branch on `endReason`; `call.failed` is for hard errors. ### Recordings With recording enabled, the payload carries `recordingUrl`, a signed URL expiring at `recordingExpiresAt`. Fetch a fresh one with `GET /v1/calls/{id}/recording` and `call.id`. ### Missed-call follow-up Check for `endReason: \"no_answer\"`, then text the caller over the linked `conversationId`.
pub async fn on_call_ended(configuration: &configuration::Configuration, webhook_payload_call_ended: models::WebhookPayloadCallEnded) -> Result<(), Error<OnCallEndedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_call_ended = webhook_payload_call_ended;
let uri_str = format!("{}/call.ended", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_call_ended);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCallEndedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A call failed with a hard error before or during bridging, for example the destination rejected the SIP INVITE. ### Payload notes Carries the upstream error `code` and `message`, for example when Meta rejected the connect or Telnyx returned an error.
pub async fn on_call_failed(configuration: &configuration::Configuration, webhook_payload_call_failed: models::WebhookPayloadCallFailed) -> Result<(), Error<OnCallFailedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_call_failed = webhook_payload_call_failed;
let uri_str = format!("{}/call.failed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_call_failed);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCallFailedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A WhatsApp user accepted or rejected your call-permission request. ### When it fires Independent of any call: it reports a reply to a permission prompt. Meta permits a business-initiated call only after the consumer taps Allow, and the accept can land days before the call. ### Payload notes `response` is `accept` or `reject`. Also carries the user's number, whether the grant is permanent, and the expiry when it is not.
pub async fn on_call_permission_request(configuration: &configuration::Configuration, webhook_payload_call_permission_request: models::WebhookPayloadCallPermissionRequest) -> Result<(), Error<OnCallPermissionRequestError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_call_permission_request = webhook_payload_call_permission_request;
let uri_str = format!("{}/call.permission_request", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_call_permission_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCallPermissionRequestError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An inbound phone or WhatsApp call reached your number, or an outbound WhatsApp call was placed. ### When it fires Fires at ring time, before anyone answers; an unanswered call still emits it, then `call.ended` with `endReason: \"no_answer\"`. Outbound WhatsApp calls fire at origination with `direction: \"outbound\"`. Outbound phone calls never emit it. ### Payload notes Carries the Zernio call id, the caller and business numbers, the destination snapshot (`forwardTo`), and `contactId` and `conversationId` to message the caller with the regular send endpoints.
pub async fn on_call_received(configuration: &configuration::Configuration, webhook_payload_call_received: models::WebhookPayloadCallReceived) -> Result<(), Error<OnCallReceivedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_call_received = webhook_payload_call_received;
let uri_str = format!("{}/call.received", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_call_received);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCallReceivedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A campaign Zernio already tracked ran out of budget. TikTok only. ### When it fires Fires once per campaign when its budget runs out, at most once per 6 hours, so a daily budget that runs out again the next day is announced again. ### When it does not fire Ads seen for the first time by a sync never fire it. ### Platform notes Only TikTok reports this on the ad. Meta and Google keep such ads `ACTIVE`, so they never fire it.
pub async fn on_campaign_budget_depleted(configuration: &configuration::Configuration, webhook_payload_campaign_budget_depleted: models::WebhookPayloadCampaignBudgetDepleted) -> Result<(), Error<OnCampaignBudgetDepletedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_campaign_budget_depleted = webhook_payload_campaign_budget_depleted;
let uri_str = format!("{}/campaign.budget.depleted", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_campaign_budget_depleted);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCampaignBudgetDepletedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A campaign was created through Zernio (`source: \"zernio\"`) or detected by the sync (`source: \"platform\"`). ### When it fires Fires once the campaign row is recorded. A detected campaign arrives up to one sync interval late. ### When it does not fire History loaded when an account connects, and campaigns created more than 7 days ago, are never announced.
pub async fn on_campaign_created(configuration: &configuration::Configuration, webhook_payload_campaign_created: models::WebhookPayloadCampaignCreated) -> Result<(), Error<OnCampaignCreatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_campaign_created = webhook_payload_campaign_created;
let uri_str = format!("{}/campaign.created", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_campaign_created);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCampaignCreatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A creator joined a campaign from their invite link or the open link. ### When it fires It fires once per participant, and `participant.joinedAt` says when.
pub async fn on_campaign_participant_joined(configuration: &configuration::Configuration, webhook_payload_campaign_participant: models::WebhookPayloadCampaignParticipant) -> Result<(), Error<OnCampaignParticipantJoinedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_campaign_participant = webhook_payload_campaign_participant;
let uri_str = format!("{}/campaign_participant.joined", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_campaign_participant);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCampaignParticipantJoinedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// You removed a participant from the campaign. ### When it does not fire Removing a participant twice fires the event once.
pub async fn on_campaign_participant_removed(configuration: &configuration::Configuration, webhook_payload_campaign_participant: models::WebhookPayloadCampaignParticipant) -> Result<(), Error<OnCampaignParticipantRemovedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_campaign_participant = webhook_payload_campaign_participant;
let uri_str = format!("{}/campaign_participant.removed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_campaign_participant);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCampaignParticipantRemovedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// You suspended a participant. ### Effect They can no longer connect accounts or submit posts to this campaign. Posts they already submitted keep earning until you reject them.
pub async fn on_campaign_participant_suspended(configuration: &configuration::Configuration, webhook_payload_campaign_participant: models::WebhookPayloadCampaignParticipant) -> Result<(), Error<OnCampaignParticipantSuspendedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_campaign_participant = webhook_payload_campaign_participant;
let uri_str = format!("{}/campaign_participant.suspended", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_campaign_participant);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCampaignParticipantSuspendedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A payout through Zernio did not reach the creator. ### When it fires Stripe refused it, it stayed unconfirmed for 24 hours, or it was reversed. The amount is payable again, minus anything a rejection claws back.
pub async fn on_campaign_payout_failed(configuration: &configuration::Configuration, webhook_payload_campaign_payout: models::WebhookPayloadCampaignPayout) -> Result<(), Error<OnCampaignPayoutFailedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_campaign_payout = webhook_payload_campaign_payout;
let uri_str = format!("{}/campaign_payout.failed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_campaign_payout);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCampaignPayoutFailedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A participant's held earnings matured and became payable. ### Payload notes `payout.payableCents` is the participant's whole payable balance, the amount to pay when you pay from your own rails.
pub async fn on_campaign_payout_payable(configuration: &configuration::Configuration, webhook_payload_campaign_payout: models::WebhookPayloadCampaignPayout) -> Result<(), Error<OnCampaignPayoutPayableError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_campaign_payout = webhook_payload_campaign_payout;
let uri_str = format!("{}/campaign_payout.payable", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_campaign_payout);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCampaignPayoutPayableError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A payout to a participant was recorded. ### Payload notes `payout.settlement` holds the amount and the reference. `recorded` is true when the money moved outside Zernio.
pub async fn on_campaign_payout_settled(configuration: &configuration::Configuration, webhook_payload_campaign_payout: models::WebhookPayloadCampaignPayout) -> Result<(), Error<OnCampaignPayoutSettledError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_campaign_payout = webhook_payload_campaign_payout;
let uri_str = format!("{}/campaign_payout.settled", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_campaign_payout);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCampaignPayoutSettledError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// You approved a submission. ### Earnings What the submission earned so far moves to owed with the campaign hold. Later earnings post straight to owed.
pub async fn on_campaign_submission_approved(configuration: &configuration::Configuration, webhook_payload_campaign_submission: models::WebhookPayloadCampaignSubmission) -> Result<(), Error<OnCampaignSubmissionApprovedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_campaign_submission = webhook_payload_campaign_submission;
let uri_str = format!("{}/campaign_submission.approved", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_campaign_submission);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCampaignSubmissionApprovedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A submission gained a fraud flag it did not carry before, at submission or on a later sync. ### Flags Flags include `duplicate_post`, `view_spike`, `low_authenticity` and `x_read_cap` (the campaign's X read budget is spent). `submission.flags` lists every flag it carries. Zernio never rejects on its own; the decision is yours.
pub async fn on_campaign_submission_flagged(configuration: &configuration::Configuration, webhook_payload_campaign_submission: models::WebhookPayloadCampaignSubmission) -> Result<(), Error<OnCampaignSubmissionFlaggedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_campaign_submission = webhook_payload_campaign_submission;
let uri_str = format!("{}/campaign_submission.flagged", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_campaign_submission);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCampaignSubmissionFlaggedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A submission is ready for your review. ### When it fires A CPM submission reached `minViewsToEarn`, a pool submission reached `minViewsToQualify`, and per post submissions arrive here after their first accrual.
pub async fn on_campaign_submission_pending_review(configuration: &configuration::Configuration, webhook_payload_campaign_submission: models::WebhookPayloadCampaignSubmission) -> Result<(), Error<OnCampaignSubmissionPendingReviewError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_campaign_submission = webhook_payload_campaign_submission;
let uri_str = format!("{}/campaign_submission.pending_review", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_campaign_submission);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCampaignSubmissionPendingReviewError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A creator submitted a post to a campaign, Zernio opened its tracking window and took the first view sample.
pub async fn on_campaign_submission_received(configuration: &configuration::Configuration, webhook_payload_campaign_submission: models::WebhookPayloadCampaignSubmission) -> Result<(), Error<OnCampaignSubmissionReceivedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_campaign_submission = webhook_payload_campaign_submission;
let uri_str = format!("{}/campaign_submission.received", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_campaign_submission);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCampaignSubmissionReceivedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// You rejected a submission and its tracking window was cancelled. ### Earnings Its unsettled earnings go back to the campaign budget.
pub async fn on_campaign_submission_rejected(configuration: &configuration::Configuration, webhook_payload_campaign_submission: models::WebhookPayloadCampaignSubmission) -> Result<(), Error<OnCampaignSubmissionRejectedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_campaign_submission = webhook_payload_campaign_submission;
let uri_str = format!("{}/campaign_submission.rejected", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_campaign_submission);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCampaignSubmissionRejectedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A campaign was edited through Zernio (`source: \"zernio\"`), or outside Zernio and detected by the sync (`source: \"platform\"`). ### When it fires Fires after the platform and Zernio both accepted the edit. Outside edits arrive up to one sync interval late, and only to the user whose sync saw them. ### Deduplication Events are not deduplicated, so every edit is announced. Use the event `id` to drop repeats. ### Payload notes `changes` lists the edited fields: `name`, `status` (the campaign's own on/off switch), `budget`, `bid` or `settings`. Ignore unknown values. It never carries old or new values, so read the campaign. ### What the sync detects From the sync, `changes` covers only `name`, `status` and `schedule`. Schedule is detected only on Google, LinkedIn, Pinterest and OpenAI Ads. ### When it does not fire Budget edits made outside Zernio and history loaded at connect are not announced. Ad set edits arrive as `ad_set.updated`. Ad rule changes arrive as `ad_rule.triggered`. ### Google sub-resources Edits to ad schedule, targeting, negative keywords, conversion goals, assets, asset groups and listing group filters are not announced.
pub async fn on_campaign_updated(configuration: &configuration::Configuration, webhook_payload_campaign_updated: models::WebhookPayloadCampaignUpdated) -> Result<(), Error<OnCampaignUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_campaign_updated = webhook_payload_campaign_updated;
let uri_str = format!("{}/campaign.updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_campaign_updated);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCampaignUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A new comment arrived on a tracked post. ### Platform notes Delivered for Instagram, Facebook, Threads, YouTube, LinkedIn, Bluesky, Reddit and TikTok. X/Twitter does not fire it. TikTok needs an account connected through the TikTok for Business app. ### Delivery timing Instagram, Facebook, Threads and TikTok arrive in real time from the platform's webhook. The rest are poll-driven, so delivery is not instant. ### Live comments On Instagram, `comment.isLive: true` marks a comment made during a live broadcast. The key is absent on every other comment. ### Ads `comment.ad` is present only on comments made on paid content, so `if (comment.ad)` filters ad-driven comments. ### Ad fields Instagram carries `ad.id` and `ad.title`. Facebook carries `ad.promotionStatus`: `active` for boosted organic posts, `ineligible` for dark post creatives. ### Instagram author profile Comments may carry `comment.author.instagramProfile` (`isFollower`, `isFollowing`, `followerCount`, `isVerified`). An absent object means unknown, never \"not a follower\". ### Why the profile is often absent Meta reveals the follow relationship only for people who have messaged the account, and commenting does not grant that consent. The object is absent for most first-time commenters.
pub async fn on_comment_received(configuration: &configuration::Configuration, webhook_payload_comment: models::WebhookPayloadComment) -> Result<(), Error<OnCommentReceivedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_comment = webhook_payload_comment;
let uri_str = format!("{}/comment.received", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_comment);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCommentReceivedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An order was placed in the store. ### Payload notes `resource.status` is its normalized state at that moment. Read the order with `GET /v1/commerce/orders/{orderId}?accountId=...`. Fires once per Zernio account.
pub async fn on_commerce_order_created(configuration: &configuration::Configuration, webhook_payload_commerce_order: models::WebhookPayloadCommerceOrder) -> Result<(), Error<OnCommerceOrderCreatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_commerce_order = webhook_payload_commerce_order;
let uri_str = format!("{}/commerce.order.created", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_commerce_order);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCommerceOrderCreatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A refund was issued on an order. ### Payload notes `resource.id` is the order id, not the refund id. `resource.status` and `resource.platformStatus` are `null`. A `commerce.order.updated` usually follows for the same change.
pub async fn on_commerce_order_refunded(configuration: &configuration::Configuration, webhook_payload_commerce_order: models::WebhookPayloadCommerceOrder) -> Result<(), Error<OnCommerceOrderRefundedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_commerce_order = webhook_payload_commerce_order;
let uri_str = format!("{}/commerce.order.refunded", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_commerce_order);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCommerceOrderRefundedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An order changed in the store, such as payment, fulfilment, cancellation or edits. ### Payload notes `resource.status` is the new state. Refunds also fire it. Fires once per Zernio account connected to the store.
pub async fn on_commerce_order_updated(configuration: &configuration::Configuration, webhook_payload_commerce_order: models::WebhookPayloadCommerceOrder) -> Result<(), Error<OnCommerceOrderUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_commerce_order = webhook_payload_commerce_order;
let uri_str = format!("{}/commerce.order.updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_commerce_order);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCommerceOrderUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A product was created in a connected Shopify store or WooCommerce site. ### Payload notes `resource.id` is the store's product id. Read the product with `GET /v1/commerce/products/{productId}?accountId=...`. Fires once per Zernio account connected to the store.
pub async fn on_commerce_product_created(configuration: &configuration::Configuration, webhook_payload_commerce_product: models::WebhookPayloadCommerceProduct) -> Result<(), Error<OnCommerceProductCreatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_commerce_product = webhook_payload_commerce_product;
let uri_str = format!("{}/commerce.product.created", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_commerce_product);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCommerceProductCreatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A product was deleted in the store. ### Payload notes `resource.status` and `resource.platformStatus` are `null`. Fires once per Zernio account connected to the store.
pub async fn on_commerce_product_deleted(configuration: &configuration::Configuration, webhook_payload_commerce_product: models::WebhookPayloadCommerceProduct) -> Result<(), Error<OnCommerceProductDeletedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_commerce_product = webhook_payload_commerce_product;
let uri_str = format!("{}/commerce.product.deleted", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_commerce_product);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCommerceProductDeletedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A product changed in the store, or WooCommerce restored it from the trash. ### Payload notes Fields, status, variants or prices changed; read the product for what. There is no restored event. Fires once per Zernio account connected to the store.
pub async fn on_commerce_product_updated(configuration: &configuration::Configuration, webhook_payload_commerce_product: models::WebhookPayloadCommerceProduct) -> Result<(), Error<OnCommerceProductUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_commerce_product = webhook_payload_commerce_product;
let uri_str = format!("{}/commerce.product.updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_commerce_product);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCommerceProductUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A contact was deleted in Google Contacts or Outlook. ### Effect Zernio removes its email channel for that account; the contact stays when other channels remain. It arrives up to a day after the change, from the daily sync.
pub async fn on_contact_deleted(configuration: &configuration::Configuration, webhook_payload_contact: models::WebhookPayloadContact) -> Result<(), Error<OnContactDeletedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_contact = webhook_payload_contact;
let uri_str = format!("{}/contact.deleted", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_contact);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnContactDeletedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A contact custom field changed value; `field` is the field slug. ### When it fires Once per custom field whose value a write changed. Writing the current value fires nothing. ### Payload notes `previousValue` is `null` when the field was not set. `value` is `null` when it was removed.
pub async fn on_contact_field_changed(configuration: &configuration::Configuration, webhook_payload_contact_field_changed: models::WebhookPayloadContactFieldChanged) -> Result<(), Error<OnContactFieldChangedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_contact_field_changed = webhook_payload_contact_field_changed;
let uri_str = format!("{}/contact.field_changed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_contact_field_changed);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnContactFieldChangedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A tag was added to a contact by the API, a workflow `add_tag` node or a comment-automation click. ### When it fires Once per tag a write actually added. Re-adding a tag the contact already has fires nothing. ### When it does not fire Creating a contact with tags fires nothing. Only changes to an existing contact do.
pub async fn on_contact_tag_added(configuration: &configuration::Configuration, webhook_payload_contact_tag: models::WebhookPayloadContactTag) -> Result<(), Error<OnContactTagAddedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_contact_tag = webhook_payload_contact_tag;
let uri_str = format!("{}/contact.tag_added", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_contact_tag);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnContactTagAddedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A tag was removed from a contact. ### When it fires Once per tag a write actually removed.
pub async fn on_contact_tag_removed(configuration: &configuration::Configuration, webhook_payload_contact_tag: models::WebhookPayloadContactTag) -> Result<(), Error<OnContactTagRemovedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_contact_tag = webhook_payload_contact_tag;
let uri_str = format!("{}/contact.tag_removed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_contact_tag);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnContactTagRemovedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A contact sync added or changed a contact; `contact.id` is the Zernio contact id. ### When it fires It fires from the daily sync of a Google Contacts or Outlook account, so up to a day after the change. It also fires when a WhatsApp coexistence address book adds or renames a contact.
pub async fn on_contact_updated(configuration: &configuration::Configuration, webhook_payload_contact: models::WebhookPayloadContact) -> Result<(), Error<OnContactUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_contact = webhook_payload_contact;
let uri_str = format!("{}/contact.updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_contact);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnContactUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// Control of a conversation moved under Meta's handover protocol (`messaging_handovers`). ### Owner values `control.owner` is `ai_agent` (Meta Business Agent, WhatsApp), `app` (you) or `other` (a WhatsApp partner app, or a receiver such as Page Inbox on Messenger and Instagram). ### Control fields `control.previousOwner` is `null` when no handover touched the thread. `control.ownerAppId` is the new owner's Meta app id when named (Page Inbox is `263902037430900`). `control.metadata` is the transferring app's note, verbatim. ### WhatsApp Meta Business Agent took the conversation, handed it to you, or another partner app took it. While `ai_agent` owns it, its replies arrive on `message.sent` with `source: \"meta_business_agent\"`. ### Taking control on WhatsApp Sending any message through the inbox takes control back. To hand it to the agent without sending, call `POST /v1/inbox/conversations/{conversationId}/thread-control` with `action: \"release\"`. ### Facebook and Instagram Another app on the Page passed the thread to you, or took or received it. While you are not the owner, sends answer `409` `not_thread_owner`. ### Taking control on Facebook and Instagram Call `POST /v1/inbox/conversations/{conversationId}/thread-control` with `action: \"take\"`, or `\"request\"` to ask the owner to pass it. Both answer 400 `platform_not_supported` on Instagram Login connections. ### When it does not fire A repeat report of the same owner fires nothing. A `request` changes nothing until the owner passes the thread. ### Standby messages While another app owns the conversation, inbound messages arrive on `message.received` with `metadata.standby: true`.
pub async fn on_conversation_control_changed(configuration: &configuration::Configuration, webhook_payload_conversation_control_changed: models::WebhookPayloadConversationControlChanged) -> Result<(), Error<OnConversationControlChangedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_conversation_control_changed = webhook_payload_conversation_control_changed;
let uri_str = format!("{}/conversation.control_changed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_conversation_control_changed);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnConversationControlChangedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A new conversation began between a connected account and a contact, in either direction, on any DM platform. ### When it fires Once per conversation, the first time it appears. Covers Instagram, Messenger, WhatsApp, Telegram, X, Reddit, Bluesky, TikTok, SMS, RCS, iMessage, Slack and email. ### When it does not fire DM history replayed when an Instagram or Facebook account connects never fires it.
pub async fn on_conversation_started(configuration: &configuration::Configuration, webhook_payload_conversation_started: models::WebhookPayloadConversationStarted) -> Result<(), Error<OnConversationStartedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_conversation_started = webhook_payload_conversation_started;
let uri_str = format!("{}/conversation.started", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_conversation_started);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnConversationStartedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A campaign's earnings reached its budget. ### When it fires Nothing more accrues until budget is freed. It fires once per campaign.
pub async fn on_creator_campaign_budget_exhausted(configuration: &configuration::Configuration, webhook_payload_creator_campaign: models::WebhookPayloadCreatorCampaign) -> Result<(), Error<OnCreatorCampaignBudgetExhaustedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_creator_campaign = webhook_payload_creator_campaign;
let uri_str = format!("{}/creator_campaign.budget_exhausted", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_creator_campaign);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCreatorCampaignBudgetExhaustedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A campaign closed, either because you closed it or because `endsAt` passed. ### When it fires After `endsAt`, the campaign closes once every tracking window had its final read. A pool campaign is split among participants at this moment.
pub async fn on_creator_campaign_closed(configuration: &configuration::Configuration, webhook_payload_creator_campaign: models::WebhookPayloadCreatorCampaign) -> Result<(), Error<OnCreatorCampaignClosedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_creator_campaign = webhook_payload_creator_campaign;
let uri_str = format!("{}/creator_campaign.closed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_creator_campaign);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnCreatorCampaignClosedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A file the account can reach was created in Google Drive or OneDrive. ### Platform notes A folder counts as a file. The event is pushed seconds after the change.
pub async fn on_file_created(configuration: &configuration::Configuration, webhook_payload_file: models::WebhookPayloadFile) -> Result<(), Error<OnFileCreatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_file = webhook_payload_file;
let uri_str = format!("{}/file.created", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_file);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnFileCreatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A file the account could reach was deleted or moved to the trash.
pub async fn on_file_deleted(configuration: &configuration::Configuration, webhook_payload_file: models::WebhookPayloadFile) -> Result<(), Error<OnFileDeletedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_file = webhook_payload_file;
let uri_str = format!("{}/file.deleted", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_file);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnFileDeletedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// The user picked files in a picker session; `picker.files` lists each one's `id`, `name`, `mimeType` and `kind`. ### When it fires It fires when the user finishes a hosted picker session (`POST /v1/files/picker-sessions`) and picks at least one file. Not sent on cancel. The files are readable from then on.
pub async fn on_file_picked(configuration: &configuration::Configuration, webhook_payload_file_picked: models::WebhookPayloadFilePicked) -> Result<(), Error<OnFilePickedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_file_picked = webhook_payload_file_picked;
let uri_str = format!("{}/file.picked", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_file_picked);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnFilePickedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A file the account can reach was changed, renamed or moved.
pub async fn on_file_updated(configuration: &configuration::Configuration, webhook_payload_file: models::WebhookPayloadFile) -> Result<(), Error<OnFileUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_file = webhook_payload_file;
let uri_str = format!("{}/file.updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_file);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnFileUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A new lead was submitted against a Meta Lead Gen (Instant) form and ingested via the Page `leadgen` webhook. ### Payload notes `lead.fields` maps question key to answer; multiple-choice values are the option key (for example `k1`), not the display label. ### Provenance `lead.formId`, `lead.adId` and `lead.campaignId` give provenance. `lead.adId` is null for organic or test leads. ### Consents `lead.consents` lists the answer to every custom disclaimer checkbox, for example `{ \"checkboxKey\": \"call_consent\", \"isChecked\": true }`. Route call and SMS consent into your CRM from it. Empty when the form has no checkboxes. ### Checkbox keys When no key was set on the checkbox, Meta derives `checkboxKey` from its text, so match on the full key. `GET /v1/ads/leads` and `GET /v1/ads/lead-forms/{formId}/leads` return the same array. ### Deduplication Deduplicate on `lead.leadgenId` (Meta's lead id) or the event `id`. ### Routing `account.profileId` names the Zernio profile of the Facebook account that received the lead, for multi-tenant routing. Always present, `null` only when no profile is on record. ### Requires ads enabled Needs ads enabled on the team. Zernio asks for `leads_retrieval` at Facebook consent only then; without it Meta refuses the Page's `leadgen` subscription. Accounts connected earlier need a reconnect. ### Lost subscription A Page can lose its `leadgen` subscription while other events keep arriving. `leadgen: false` (with a `warning`) on the Page's webhook subscription means leads are not reaching Zernio; re-subscribe the Page.
pub async fn on_lead_received(configuration: &configuration::Configuration, webhook_payload_lead: models::WebhookPayloadLead) -> Result<(), Error<OnLeadReceivedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_lead = webhook_payload_lead;
let uri_str = format!("{}/lead.received", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_lead);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnLeadReceivedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A sender deleted (unsent) a message on Instagram or WhatsApp. ### Platform notes Instagram reports incoming unsends. WhatsApp reports both directions, including business deletions through the Cloud API or a Coexistence app. `message.direction` tells them apart. ### Payload notes The payload keeps the pre-delete `text` and `attachments` for moderation, compliance or archival. The Zernio dashboard does not show this content.
pub async fn on_message_deleted(configuration: &configuration::Configuration, webhook_payload_message_deleted: models::WebhookPayloadMessageDeleted) -> Result<(), Error<OnMessageDeletedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_message_deleted = webhook_payload_message_deleted;
let uri_str = format!("{}/message.deleted", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_message_deleted);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnMessageDeletedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An outgoing message was delivered to the recipient on WhatsApp, Facebook Messenger, SMS, RCS or iMessage. ### Platform notes On WhatsApp, `pricing` and `billingConversation` carry Meta's billing context for the message.
pub async fn on_message_delivered(configuration: &configuration::Configuration, webhook_payload_message_delivery_status: models::WebhookPayloadMessageDeliveryStatus) -> Result<(), Error<OnMessageDeliveredError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_message_delivery_status = webhook_payload_message_delivery_status;
let uri_str = format!("{}/message.delivered", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_message_delivery_status);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnMessageDeliveredError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A sender edited a previously sent message on Instagram, Facebook Messenger, Telegram or WhatsApp. ### Payload notes `editHistory` holds every prior version, oldest first. `message.text` is the latest version.
pub async fn on_message_edited(configuration: &configuration::Configuration, webhook_payload_message_edited: models::WebhookPayloadMessageEdited) -> Result<(), Error<OnMessageEditedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_message_edited = webhook_payload_message_edited;
let uri_str = format!("{}/message.edited", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_message_edited);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnMessageEditedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An outgoing message failed to deliver on WhatsApp, SMS, RCS or iMessage. ### Payload notes `error` carries `code`, `title` and `message` from the platform, for example `131026` for an unreachable WhatsApp recipient. On SMS it carries the carrier's error code.
pub async fn on_message_failed(configuration: &configuration::Configuration, webhook_payload_message_delivery_status: models::WebhookPayloadMessageDeliveryStatus) -> Result<(), Error<OnMessageFailedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_message_delivery_status = webhook_payload_message_delivery_status;
let uri_str = format!("{}/message.failed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_message_delivery_status);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnMessageFailedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A WhatsApp recipient played a voice message you sent, reported the first time they play it.
pub async fn on_message_played(configuration: &configuration::Configuration, webhook_payload_message_delivery_status: models::WebhookPayloadMessageDeliveryStatus) -> Result<(), Error<OnMessagePlayedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_message_delivery_status = webhook_payload_message_delivery_status;
let uri_str = format!("{}/message.played", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_message_delivery_status);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnMessagePlayedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An outgoing message was read by the recipient on WhatsApp, Facebook Messenger, Instagram or RCS.
pub async fn on_message_read(configuration: &configuration::Configuration, webhook_payload_message_delivery_status: models::WebhookPayloadMessageDeliveryStatus) -> Result<(), Error<OnMessageReadError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_message_delivery_status = webhook_payload_message_delivery_status;
let uri_str = format!("{}/message.read", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_message_delivery_status);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnMessageReadError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A new message arrived in the inbox; `message.text`, `message.attachments[]` and `message.sender` describe it. ### Standby While another app owns the conversation it carries `metadata.standby: true`. Zernio runs no workflow or keyword automation on it. A bot must skip standby messages, or on WhatsApp it takes the conversation from the agent. ### Interactive replies Button and list taps, flow responses and orders arrive under `metadata` (`interactiveType`, `interactiveId`, `flowResponseData`, `order`). Only a referral that arrives without a message becomes `referral.received`. ### Platform notes New email from Google and Microsoft mailboxes arrives as this event.
pub async fn on_message_received(configuration: &configuration::Configuration, webhook_payload_message: models::WebhookPayloadMessage) -> Result<(), Error<OnMessageReceivedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_message = webhook_payload_message;
let uri_str = format!("{}/message.received", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_message);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnMessageReceivedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A message was sent through the API, the dashboard, or the WhatsApp Business app on Coexistence numbers. ### Sender `message.sentVia` is one of `human`, `api`, `broadcast`, `sequence`, `workflow`, `comment_automation` or `bulk-api`. It is `null` for sends from the platform's own app and for older messages; treat `null` as unknown, never as human. ### Attribution keys `automationId`, `workflowId`, `executionId`, `broadcastId` and `sequenceId` are always present. Each is `null` unless that kind of sender produced the message. ### Quote replies A quote-reply sent through the API carries `metadata.quotedMessageId`. One sent from the WhatsApp Business or Instagram app does not. ### Platform notes On Instagram and Facebook the attribution can be missing when Meta's echo of a send reaches Zernio before the send is recorded. On WhatsApp, Meta Business Agent replies carry `source: \"meta_business_agent\"`.
pub async fn on_message_sent(configuration: &configuration::Configuration, webhook_payload_message_sent: models::WebhookPayloadMessageSent) -> Result<(), Error<OnMessageSentError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_message_sent = webhook_payload_message_sent;
let uri_str = format!("{}/message.sent", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_message_sent);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnMessageSentError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A country you watch has deliverable phone numbers again; fires once per watch. ### When it fires Fired by the 6-hourly stock sweep, before you own a number in that country. The watch (`POST /v1/phone-numbers/stock-watches`) is then consumed. ### Payload notes `stock.country` is the watched country. `stock.types[]` lists each number type in stock with its `availableCount` at sweep time. Numbers are first come, first served; buy with `POST /v1/phone-numbers/purchase`.
pub async fn on_phone_number_stock_available(configuration: &configuration::Configuration, webhook_payload_phone_number_stock_available: models::WebhookPayloadPhoneNumberStockAvailable) -> Result<(), Error<OnPhoneNumberStockAvailableError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_phone_number_stock_available = webhook_payload_phone_number_stock_available;
let uri_str = format!("{}/phone_number.stock_available", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_phone_number_stock_available);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnPhoneNumberStockAvailableError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A tracked post's authenticity score crossed 40, in either direction. ### When it fires Only while the tracking window is open. A post's first score never fires it. ### Payload notes Carries `score`, `previousScore`, `confidence` and `reasons`.
pub async fn on_post_authenticity_changed(configuration: &configuration::Configuration, webhook_payload_post_authenticity_changed: models::WebhookPayloadPostAuthenticityChanged) -> Result<(), Error<OnPostAuthenticityChangedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_post_authenticity_changed = webhook_payload_post_authenticity_changed;
let uri_str = format!("{}/post.authenticity_changed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_post_authenticity_changed);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnPostAuthenticityChangedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A scheduled post was cancelled because its account was disconnected, and nothing published. ### When it fires A multi-platform post fires it only once every platform entry is cancelled. If a platform already published, the rollup is `post.partial` instead. ### When it does not fire `DELETE /v1/posts/{postId}` removes the post without sending this event.
pub async fn on_post_cancelled(configuration: &configuration::Configuration, webhook_payload_post: models::WebhookPayloadPost) -> Result<(), Error<OnPostCancelledError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_post = webhook_payload_post;
let uri_str = format!("{}/post.cancelled", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_post);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnPostCancelledError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A post authored natively on the platform, outside Zernio, was detected for the first time. ### When it fires Detected by a background sync roughly hourly, not in real time. Example: a Google Business Profile post created in the Google interface. ### Payload notes `post.source` is always `\"external\"` and `post.id` is the platform-native post id. ### First sync backfill On a freshly connected account, every existing native post fires it once. Treat it as an idempotent upsert keyed on `post.id`.
pub async fn on_post_external_created(configuration: &configuration::Configuration, webhook_payload_external_post: models::WebhookPayloadExternalPost) -> Result<(), Error<OnPostExternalCreatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_external_post = webhook_payload_external_post;
let uri_str = format!("{}/post.external.created", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_external_post);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnPostExternalCreatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A tracked native post was removed from the platform. ### Payload notes `post.deletedAt` is the detection time. ### Detection limits Coverage is bounded to the most recent posts the platform listing returns, so very old deletions may go undetected. ### When it does not fire Detection diffs against posts a prior sync already indexed. An account with no indexed post never emits it.
pub async fn on_post_external_deleted(configuration: &configuration::Configuration, webhook_payload_external_post: models::WebhookPayloadExternalPost) -> Result<(), Error<OnPostExternalDeletedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_external_post = webhook_payload_external_post;
let uri_str = format!("{}/post.external.deleted", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_external_post);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnPostExternalDeletedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A tracked native post's text or media changed on the platform. ### How edits are detected Zernio compares text and media structure and, where available, the platform's own edit timestamp. A media-URL-only refresh (rotated CDN URLs) does not fire it.
pub async fn on_post_external_updated(configuration: &configuration::Configuration, webhook_payload_external_post: models::WebhookPayloadExternalPost) -> Result<(), Error<OnPostExternalUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_external_post = webhook_payload_external_post;
let uri_str = format!("{}/post.external.updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_external_post);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnPostExternalUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A post failed on every target platform. ### When it fires Once per publishing job, after every platform target ends. Exactly one of `post.published`, `post.partial` or `post.failed` fires. ### Payload notes Each `platforms[]` entry carries `error`, `errorCategory` and `errorSource`, the same taxonomy as `platforms[]` on Get post. Branch on `errorCategory`, not on the message text.
pub async fn on_post_failed(configuration: &configuration::Configuration, webhook_payload_post: models::WebhookPayloadPost) -> Result<(), Error<OnPostFailedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_post = webhook_payload_post;
let uri_str = format!("{}/post.failed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_post);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnPostFailedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A post published on some platforms and failed on others. ### When it fires Once per publishing job, after every platform target ends. Exactly one of `post.published`, `post.partial` or `post.failed` fires. ### Payload notes Read `platforms[].status` to tell them apart. Failed entries carry `error`, `errorCategory` and `errorSource`.
pub async fn on_post_partial(configuration: &configuration::Configuration, webhook_payload_post: models::WebhookPayloadPost) -> Result<(), Error<OnPostPartialError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_post = webhook_payload_post;
let uri_str = format!("{}/post.partial", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_post);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnPostPartialError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A published platform target was deleted on the platform. ### When it fires Detected by a background sync roughly hourly, once per platform target. Platforms push no deletion notice, so it can trail the rollup by days. ### Payload notes `platform.status` is `deleted`. `platform.deletedAt` is the detection time, not the moment of deletion. ### Detection limits Detection is listing-based: coverage is bounded to the posts the listing returns, and rare false positives happen. The event is not retracted when the post reappears. Re-check before deleting. ### When it does not fire Detection diffs against posts a prior sync already indexed. An account with no indexed post never emits it.
pub async fn on_post_platform_deleted(configuration: &configuration::Configuration, webhook_payload_post_platform: models::WebhookPayloadPostPlatform) -> Result<(), Error<OnPostPlatformDeletedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_post_platform = webhook_payload_post_platform;
let uri_str = format!("{}/post.platform.deleted", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_post_platform);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnPostPlatformDeletedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// One platform target failed permanently. ### When it fires Only on permanent failure; retryable errors stay silent. The rollup (`post.failed` or `post.partial`) fires separately once every platform ends. ### After a publish It can fire for a target that already emitted `post.platform.published`, if background reconciliation finds the publish never completed. ### Payload notes `platform.error` carries the platform's message. `platform.errorCategory` and `platform.errorSource` classify it, so a reconnect (`auth_expired`) separates from a content fix (`user_content`).
pub async fn on_post_platform_failed(configuration: &configuration::Configuration, webhook_payload_post_platform: models::WebhookPayloadPostPlatform) -> Result<(), Error<OnPostPlatformFailedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_post_platform = webhook_payload_post_platform;
let uri_str = format!("{}/post.platform.failed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_post_platform);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnPostPlatformFailedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// One platform target finished publishing, without waiting for the other targets. ### When it fires Once per platform target, as soon as it finishes. A cross-post to 2 accounts on the same platform produces 2 events. Use `post.published` for the post-level rollup. ### Payload notes `platform` carries the platform post id and URL. `account` identifies the connected account. ### Later reconciliation If a target later fails background reconciliation, `post.platform.failed` fires for the same target afterward.
pub async fn on_post_platform_published(configuration: &configuration::Configuration, webhook_payload_post_platform: models::WebhookPayloadPostPlatform) -> Result<(), Error<OnPostPlatformPublishedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_post_platform = webhook_payload_post_platform;
let uri_str = format!("{}/post.platform.published", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_post_platform);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnPostPlatformPublishedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// Every platform target of a post published. ### When it fires Once per publishing job, after every platform target ends. Exactly one of `post.published`, `post.partial` or `post.failed` fires. ### Payload notes Each `platforms[]` entry carries the `platformPostId` and `publishedUrl`.
pub async fn on_post_published(configuration: &configuration::Configuration, webhook_payload_post: models::WebhookPayloadPost) -> Result<(), Error<OnPostPublishedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_post = webhook_payload_post;
let uri_str = format!("{}/post.published", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_post);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnPostPublishedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A recycling schedule cloned a published post for republishing. ### Payload notes `post.id` is the new clone's id. The clone emits its own `post.scheduled`.
pub async fn on_post_recycled(configuration: &configuration::Configuration, webhook_payload_post: models::WebhookPayloadPost) -> Result<(), Error<OnPostRecycledError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_post = webhook_payload_post;
let uri_str = format!("{}/post.recycled", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_post);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnPostRecycledError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A post entered the scheduled state. ### When it fires Created with a schedule (with `publishNow`, accepted and queued), promoted from draft, added to a queue, retried after failing, or created as a recycled clone. ### Approval and repeats A post saved with `requiresApproval: true` fires it on approval, not at creation. One post can emit it more than once. ### When it does not fire Editing or moving an already-scheduled post to another time does not fire it.
pub async fn on_post_scheduled(configuration: &configuration::Configuration, webhook_payload_post: models::WebhookPayloadPost) -> Result<(), Error<OnPostScheduledError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_post = webhook_payload_post;
let uri_str = format!("{}/post.scheduled", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_post);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnPostScheduledError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A published TikTok post's public URL became available. ### When it fires TikTok exposes the video id asynchronously, often minutes after upload, so `post.published` can carry an empty `publishedUrl`. Fires at most once per platform target. For a draft, it fires when the creator posts the draft publicly from the TikTok app. ### Payload notes Delivers `platform.publishedUrl` and the resolved `platform.platformPostId`. Same shape as `post.platform.published`. ### When it does not fire Private posts, which have no public URL, and drafts the creator never posts.
pub async fn on_post_tik_tok_url_resolved(configuration: &configuration::Configuration, webhook_payload_post_platform: models::WebhookPayloadPostPlatform) -> Result<(), Error<OnPostTikTokUrlResolvedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_post_platform = webhook_payload_post_platform;
let uri_str = format!("{}/post.tiktok.url_resolved", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_post_platform);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnPostTikTokUrlResolvedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A post's tracking window ended and its final analytics read finished. ### When it fires Once per window. A cancelled window never fires it. ### Payload notes `final` holds the closing metrics, or is null when no sample could be read. When the post was deleted, it is the last sample held, if any. ### Completion reasons `window.completionReason` is `final_read` (the read succeeded), `unreachable` (the sync failed or no sample exists) or `post_deleted` (the post is gone).
pub async fn on_post_tracking_completed(configuration: &configuration::Configuration, webhook_payload_post_tracking_completed: models::WebhookPayloadPostTrackingCompleted) -> Result<(), Error<OnPostTrackingCompletedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_post_tracking_completed = webhook_payload_post_tracking_completed;
let uri_str = format!("{}/post.tracking_completed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_post_tracking_completed);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnPostTrackingCompletedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An RCS agent moved into a new customer-visible status; `status` is the new one. ### Statuses `changes_requested` (note in `reason`), `brand_vetting`, `agent_review`, `testing`, `launch_review`, `launching`, `live`, `rejected` (`reason` says why), `deactivated`. In `testing`, add test phones, then file the launch; a `reason` means it bounced. ### When it fires Fires once per move into a status. `requested` sends nothing. Overlapping status checks never send the same status twice in a row. ### Payload notes `agent.profileId` is the owning profile. `agent.accountId` is `null` when the agent has no linked account.
pub async fn on_rcs_agent_status_updated(configuration: &configuration::Configuration, on_rcs_agent_status_updated_request: models::OnRcsAgentStatusUpdatedRequest) -> Result<(), Error<OnRcsAgentStatusUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_on_rcs_agent_status_updated_request = on_rcs_agent_status_updated_request;
let uri_str = format!("{}/rcs.agent.status_updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_on_rcs_agent_status_updated_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnRcsAgentStatusUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A participant added or removed an emoji reaction on a message on Instagram, Facebook, WhatsApp, Telegram, Slack or TikTok. ### Payload notes Sent as its own event, never as `message.received`. `reaction.action` is `added` or `removed`. `reaction.platformMessageId` is always present; `reaction.messageId` is the Zernio id when resolvable. ### Removals On WhatsApp, Instagram and Facebook removals, `reaction.emoji` is an empty string because the platform does not say which emoji went away. Match on `platformMessageId` to clear a mirrored reaction. ### TikTok A like or emoji reaction on a DM arrives only as this event, never as an empty `message.received`. `platformMessageId` is the TikTok id of the liked message. AI emoji reactions can have an empty `emoji`. ### Telegram The bot must be an administrator in the chat. Reactions in private chats are never delivered to bots. ### Accounts connected before August 2026 Instagram and Facebook accounts connected before August 2026 do not receive this event until their webhook subscription is refreshed. Reconnect them, or re-subscribe a Facebook Page without a reconnect.
pub async fn on_reaction_received(configuration: &configuration::Configuration, webhook_payload_reaction: models::WebhookPayloadReaction) -> Result<(), Error<OnReactionReceivedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_reaction = webhook_payload_reaction;
let uri_str = format!("{}/reaction.received", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_reaction);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnReactionReceivedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// Someone opened an existing Instagram or Messenger thread through an ig.me or m.me `ref` link or returning ad click. ### Payload notes Meta's referral object is forwarded verbatim: `ref` and `source` for links, `ad_id` and `ads_context_data` for ad clicks. ### When it does not fire A referral that rides an inbound message arrives on `message.received` under `metadata.referral` instead. The two never fire for the same click. ### Stored referral The first referral captured on a conversation is also persisted on it (`metadata` on `GET /v1/inbox/conversations`).
pub async fn on_referral_received(configuration: &configuration::Configuration, webhook_payload_referral: models::WebhookPayloadReferral) -> Result<(), Error<OnReferralReceivedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_referral = webhook_payload_referral;
let uri_str = format!("{}/referral.received", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_referral);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnReferralReceivedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// Google Business Profile stopped returning a review, for example after its spam filter removed it. ### When it fires Zernio detects it by polling, so it usually fires 6 to 12 hours after the review disappears. Only locations covered by a webhook subscribed to `review.deleted` or `review.restored` are checked. ### Restores If the review comes back, `review.restored` fires, so a hidden then restored review produces `review.deleted` then `review.restored`. A `review.updated` can arrive for a deleted review; the next check restores it. ### Payload notes `review.id` is the full review name, the same value `review.new` sent. It may arrive for a review id you never received `review.new` for, so ignore ids you do not know.
pub async fn on_review_deleted(configuration: &configuration::Configuration, webhook_payload_review_deleted: models::WebhookPayloadReviewDeleted) -> Result<(), Error<OnReviewDeletedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_review_deleted = webhook_payload_review_deleted;
let uri_str = format!("{}/review.deleted", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_review_deleted);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnReviewDeletedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A new review was posted on a connected Google Business Profile account, in real time through Pub/Sub.
pub async fn on_review_new(configuration: &configuration::Configuration, webhook_payload_review_new: models::WebhookPayloadReviewNew) -> Result<(), Error<OnReviewNewError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_review_new = webhook_payload_review_new;
let uri_str = format!("{}/review.new", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_review_new);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnReviewNewError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// Google returned a review previously reported by `review.deleted`; the payload has the same shape as `review.new`. ### When it fires It may reach a webhook that subscribed after the deletion, so ignore ids you do not know.
pub async fn on_review_restored(configuration: &configuration::Configuration, webhook_payload_review_restored: models::WebhookPayloadReviewRestored) -> Result<(), Error<OnReviewRestoredError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_review_restored = webhook_payload_review_restored;
let uri_str = format!("{}/review.restored", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_review_restored);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnReviewRestoredError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A Google Business Profile review changed: the reviewer edited it, or its reply was added, edited or removed. ### Reply through the API A reply sent through the Zernio API fires the event immediately. The periodic check then reports it again with the full review payload, so expect a second delivery. ### Replies written in Google Google sends no notification for replies written in its interface. The periodic check detects them, usually within 6 hours for reviews updated in the last 30 days, about 7 days for older. ### Checks Only teams with a webhook subscribed to `review.updated` are checked. A removed reply, through the API or in Google, fires from the periodic check with `review.hasReply` set to `false`. ### Payload notes Same shape as `review.new`. When a reply is present, `review.hasReply` is `true` and `review.reply` is populated.
pub async fn on_review_updated(configuration: &configuration::Configuration, webhook_payload_review_updated: models::WebhookPayloadReviewUpdated) -> Result<(), Error<OnReviewUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_review_updated = webhook_payload_review_updated;
let uri_str = format!("{}/review.updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_review_updated);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnReviewUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A contact was enrolled in a sequence, through the API or a workflow `enroll_sequence` node.
pub async fn on_sequence_enrolled(configuration: &configuration::Configuration, webhook_payload_sequence_enrollment: models::WebhookPayloadSequenceEnrollment) -> Result<(), Error<OnSequenceEnrolledError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_sequence_enrollment = webhook_payload_sequence_enrollment;
let uri_str = format!("{}/sequence.enrolled", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_sequence_enrollment);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnSequenceEnrolledError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A contact left a sequence; `exitReason` says why. ### Exit reasons - `completed`: the last step was sent. - `replied` - `manual`: unenrolled through the API. - `failed`: the step kept failing to send. - `unsubscribed`
pub async fn on_sequence_exited(configuration: &configuration::Configuration, webhook_payload_sequence_enrollment: models::WebhookPayloadSequenceEnrollment) -> Result<(), Error<OnSequenceExitedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_sequence_enrollment = webhook_payload_sequence_enrollment;
let uri_str = format!("{}/sequence.exited", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_sequence_enrollment);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnSequenceExitedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An SMS registration is waiting on its owner; `reason` says why. ### Reasons - `changes_requested`: answer `message` via `POST /v1/sms/registrations/{id}/respond`. - `otp_required`: submit the texted code via `POST /v1/sms/registrations/{id}/verify-otp`; no `message`. - `carrier_info_required`: expires after 7 days. ### When it fires Fires once per new request and once per OTP or carrier request, not on follow-up messages. A carrier rejection alone does not fire it.
pub async fn on_sms_registration_action_required(configuration: &configuration::Configuration, on_sms_registration_action_required_request: models::OnSmsRegistrationActionRequiredRequest) -> Result<(), Error<OnSmsRegistrationActionRequiredError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_on_sms_registration_action_required_request = on_sms_registration_action_required_request;
let uri_str = format!("{}/sms.registration.action_required", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_on_sms_registration_action_required_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnSmsRegistrationActionRequiredError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An SMS registration changed status; `status` is the new one. ### Statuses - `changes_requested`: answers needed. - `requested`: submitted, resubmitted, or your answers are back in review. - `pending`: with the carriers. - `approved`: live, attach numbers. - `rejected`: `reason` is the carriers' words. - `deactivated` ### Rejections A carrier rejection needs nothing from you. Zernio handles the fix and resends it, so the status returns to `pending`.
pub async fn on_sms_registration_status_updated(configuration: &configuration::Configuration, on_sms_registration_status_updated_request: models::OnSmsRegistrationStatusUpdatedRequest) -> Result<(), Error<OnSmsRegistrationStatusUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_on_sms_registration_status_updated_request = on_sms_registration_status_updated_request;
let uri_str = format!("{}/sms.registration.status_updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_on_sms_registration_status_updated_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnSmsRegistrationStatusUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A support run finished with an answer, or handed the question to a person. ### Payload notes `run.status` is `completed`, or `needs_human` when Ana handed the question to a person. `run.answer` holds the answer; `run.stopReason` says why it stopped (`answered` or `human_review`, among others).
pub async fn on_support_run_completed(configuration: &configuration::Configuration, webhook_payload_support_run: models::WebhookPayloadSupportRun) -> Result<(), Error<OnSupportRunCompletedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_support_run = webhook_payload_support_run;
let uri_str = format!("{}/support.run.completed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_support_run);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnSupportRunCompletedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A support run failed or expired, and is not billed. ### Payload notes `run.status` is `failed` and `run.answer` is `null`. `run.stopReason` is `expired` when the run never finished. `run.costUsd` is 0.
pub async fn on_support_run_failed(configuration: &configuration::Configuration, webhook_payload_support_run: models::WebhookPayloadSupportRun) -> Result<(), Error<OnSupportRunFailedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_support_run = webhook_payload_support_run;
let uri_str = format!("{}/support.run.failed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_support_run);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnSupportRunFailedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// The recipient submitted the right verification code. ### Payload notes Carries `verification.verificationId`, `verification.channel` (`sms`) and `verification.to`.
pub async fn on_verification_approved(configuration: &configuration::Configuration, on_verification_approved_request: models::OnVerificationApprovedRequest) -> Result<(), Error<OnVerificationApprovedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_on_verification_approved_request = on_verification_approved_request;
let uri_str = format!("{}/verification.approved", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_on_verification_approved_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnVerificationApprovedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A verification ran out of attempts without a correct code. ### Payload notes `reason` is `max_attempts_reached`. Carries the same `verification` fields as `verification.approved`.
pub async fn on_verification_failed(configuration: &configuration::Configuration, on_verification_failed_request: models::OnVerificationFailedRequest) -> Result<(), Error<OnVerificationFailedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_on_verification_failed_request = on_verification_failed_request;
let uri_str = format!("{}/verification.failed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_on_verification_failed_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnVerificationFailedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// Zernio sent a test event to an endpoint. ### When it fires Sent when you call Test webhook or press test in the dashboard, whatever events the endpoint subscribes to. Sent once, synchronously, and never retried.
pub async fn on_webhook_test(configuration: &configuration::Configuration, webhook_payload_test: models::WebhookPayloadTest) -> Result<(), Error<OnWebhookTestError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_test = webhook_payload_test;
let uri_str = format!("{}/webhook.test", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_test);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWebhookTestError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// Meta sent an account alert for a connected WhatsApp Business Account. ### Payload notes Forwards Meta's `account_alerts` as is. `alert.severity` is `CRITICAL`, `WARNING` or `INFORMATIONAL`; `alert.type` is Meta's alert type; `alert.description` is the text. ### Who receives it An alert about one number goes to that number's account. A business-level alert goes to every connected number on the WABA.
pub async fn on_whats_app_account_alert_received(configuration: &configuration::Configuration, webhook_payload_whats_app_account_alert_received: models::WebhookPayloadWhatsAppAccountAlertReceived) -> Result<(), Error<OnWhatsAppAccountAlertReceivedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_whats_app_account_alert_received = webhook_payload_whats_app_account_alert_received;
let uri_str = format!("{}/whatsapp.account.alert_received", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_whats_app_account_alert_received);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWhatsAppAccountAlertReceivedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// Meta finished reviewing a WhatsApp display-name change on a connected number. ### When it fires Fires only on a review outcome, forwarded from Meta's `phone_number_name_update` field. A name applied without review (`AVAILABLE_WITHOUT_REVIEW`) produces no event. ### Payload notes Branch on `name.status` (`APPROVED`, `DECLINED`, `PENDING_REVIEW`). Meta's `REJECTED` maps to `DECLINED` and `DEFERRED` to `PENDING_REVIEW`, because the review is still open. `name.requestedName` and `name.rejectionReason` are Meta's values or null. ### Delivery Delivery is at-least-once; dedupe on `(account.accountId, name.status, name.requestedName)`.
pub async fn on_whats_app_account_name_status_updated(configuration: &configuration::Configuration, webhook_payload_whats_app_account_name_status_updated: models::WebhookPayloadWhatsAppAccountNameStatusUpdated) -> Result<(), Error<OnWhatsAppAccountNameStatusUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_whats_app_account_name_status_updated = webhook_payload_whats_app_account_name_status_updated;
let uri_str = format!("{}/whatsapp.account.name_status_updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_whats_app_account_name_status_updated);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWhatsAppAccountNameStatusUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A connected number's quality rating or messaging limit tier changed. ### When it fires Fires only when the rating or tier differs from the value Zernio held. A tier change Meta applies to the whole business portfolio fires once per connected number. ### Payload notes `quality.source` says which Meta signal reported it. Compare `quality.previousQualityRating` with `quality.qualityRating`, and the previous and current messaging limit tier. `quality.qualityRating` is Meta's live value (`GREEN`, `YELLOW`, `RED`). ### Delivery Delivery is at-least-once; dedupe on the event `id`.
pub async fn on_whats_app_account_quality_updated(configuration: &configuration::Configuration, webhook_payload_whats_app_account_quality_updated: models::WebhookPayloadWhatsAppAccountQualityUpdated) -> Result<(), Error<OnWhatsAppAccountQualityUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_whats_app_account_quality_updated = webhook_payload_whats_app_account_quality_updated;
let uri_str = format!("{}/whatsapp.account.quality_updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_whats_app_account_quality_updated);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWhatsAppAccountQualityUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// Meta restricted, disabled, deleted or reinstated a connected WhatsApp Business Account, or flagged a violation on it. ### When it fires Mirrors Meta's `account_update` events. They apply to the whole WhatsApp Business Account, so every connected number on it receives one event. ### Payload notes Branch on `status.status` (`restricted` or `active`) and `status.metaEvent`. `status.restrictions` lists what Meta restricted (for example `RESTRICTED_BIZ_INITIATED_MESSAGING`) and when each lifts. The same status is on the account as `platformStatus`.
pub async fn on_whats_app_account_status_updated(configuration: &configuration::Configuration, webhook_payload_whats_app_account_status_updated: models::WebhookPayloadWhatsAppAccountStatusUpdated) -> Result<(), Error<OnWhatsAppAccountStatusUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_whats_app_account_status_updated = webhook_payload_whats_app_account_status_updated;
let uri_str = format!("{}/whatsapp.account.status_updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_whats_app_account_status_updated);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWhatsAppAccountStatusUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// Meta's automatic event identification detected a lead or purchase in a Click-to-WhatsApp conversation. ### Payload notes Branch on `eventName` (`LeadSubmitted` or `Purchase`). `Purchase` may carry the detected amount in `customData` (`currency`, `value`). It carries the `ctwaClid`. ### Conversions API match key Meta omits the clid on a minority of referrals, most often WhatsApp Status placements; this event can supply it. Zernio writes it onto the conversation, so `POST /v1/whatsapp/conversions` becomes usable for it. ### Availability Detection is not available for EU, UK and JP businesses. Elsewhere the owner opts in during Embedded Signup. An endpoint subscribed on a number whose owner did not opt in receives nothing.
pub async fn on_whats_app_automatic_event(configuration: &configuration::Configuration, on_whats_app_automatic_event_request: models::OnWhatsAppAutomaticEventRequest) -> Result<(), Error<OnWhatsAppAutomaticEventError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_on_whats_app_automatic_event_request = on_whats_app_automatic_event_request;
let uri_str = format!("{}/whatsapp.automatic_event", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_on_whats_app_automatic_event_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWhatsAppAutomaticEventError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A WhatsApp user changed phone number or Meta regenerated their business-scoped user id (BSUID). ### When it fires Fires when Meta reports the user under a new phone number (`reason: \"user_changed_number\"`) or a new BSUID (`user_changed_user_id`, `user_identity_changed` or `user_id_update`). ### Payload notes `previous` and `current` carry the phone number, BSUID, parent BSUID and username. Use them to re-key records stored against the old value. ### Already applied Zernio has already moved the inbox conversation and the contact when the event arrives. `conversationId` and `contactId` point at them, or are null when there was none. ### Delivery Delivery is at-least-once; dedupe on the event `id`.
pub async fn on_whats_app_contact_identity_changed(configuration: &configuration::Configuration, webhook_payload_whats_app_contact_identity_changed: models::WebhookPayloadWhatsAppContactIdentityChanged) -> Result<(), Error<OnWhatsAppContactIdentityChangedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_whats_app_contact_identity_changed = webhook_payload_whats_app_contact_identity_changed;
let uri_str = format!("{}/whatsapp.contact.identity_changed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_whats_app_contact_identity_changed);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWhatsAppContactIdentityChangedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// The regulator asked for more information on a placed number order; nothing was rejected. ### When it fires The order stays pending, and the number stays `pending_regulatory`, until you provide the information. The status does not change. ### Payload notes `reason` carries the regulator's request verbatim when available. `requirements` lists every requirement with the reviewer's current verdict; the `declined` ones are what to fix, keyed by `requirementId`. Verdicts describe the review at `reviewedAt`. ### How to resolve Provide the missing details from the dashboard's phone-numbers page, or re-submit the fields through the remediation endpoint. The review resumes automatically.
pub async fn on_whats_app_number_action_required(configuration: &configuration::Configuration, on_whats_app_number_action_required_request: models::OnWhatsAppNumberActionRequiredRequest) -> Result<(), Error<OnWhatsAppNumberActionRequiredError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_on_whats_app_number_action_required_request = on_whats_app_number_action_required_request;
let uri_str = format!("{}/whatsapp.number.action_required", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_on_whats_app_number_action_required_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWhatsAppNumberActionRequiredError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A number you provisioned through Zernio finished setup and is ready to connect. ### When it fires Regulated (non-US) numbers can take 1 to 3 business days after the order is approved. In instant-provisioning countries this is the first event, with no review states before it.
pub async fn on_whats_app_number_activated(configuration: &configuration::Configuration, on_whats_app_number_activated_request: models::OnWhatsAppNumberActivatedRequest) -> Result<(), Error<OnWhatsAppNumberActivatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_on_whats_app_number_activated_request = on_whats_app_number_activated_request;
let uri_str = format!("{}/whatsapp.number.activated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_on_whats_app_number_activated_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWhatsAppNumberActivatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A regulated number order was declined in regulatory review and no number was activated. ### Payload notes `reason` carries the reviewer's rejection reason when available. You are never billed for a declined number. ### Remediation Resubmit corrected details and the number returns to `pending_regulatory`. It is the same number, with no new billing.
pub async fn on_whats_app_number_declined(configuration: &configuration::Configuration, on_whats_app_number_declined_request: models::OnWhatsAppNumberDeclinedRequest) -> Result<(), Error<OnWhatsAppNumberDeclinedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_on_whats_app_number_declined_request = on_whats_app_number_declined_request;
let uri_str = format!("{}/whatsapp.number.declined", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_on_whats_app_number_declined_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWhatsAppNumberDeclinedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An end customer completed a hosted KYC share link and the number entered regulatory review. ### When it fires Fires only for hosted share links (`POST /v1/phone-numbers/kyc/share`). When you submit KYC over the API, no event fires. ### What follows The number is `pending_regulatory` under your account. `whatsapp.number.activated` or `whatsapp.number.declined` follows once the provider rules on it. Update your own UI from this event instead of polling.
pub async fn on_whats_app_number_kyc_submitted(configuration: &configuration::Configuration, on_whats_app_number_kyc_submitted_request: models::OnWhatsAppNumberKycSubmittedRequest) -> Result<(), Error<OnWhatsAppNumberKycSubmittedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_on_whats_app_number_kyc_submitted_request = on_whats_app_number_kyc_submitted_request;
let uri_str = format!("{}/whatsapp.number.kyc_submitted", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_on_whats_app_number_kyc_submitted_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWhatsAppNumberKycSubmittedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A suspended number was reactivated, for example after the payment recovered, and is usable again.
pub async fn on_whats_app_number_reactivated(configuration: &configuration::Configuration, on_whats_app_number_reactivated_request: models::OnWhatsAppNumberReactivatedRequest) -> Result<(), Error<OnWhatsAppNumberReactivatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_on_whats_app_number_reactivated_request = on_whats_app_number_reactivated_request;
let uri_str = format!("{}/whatsapp.number.reactivated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_on_whats_app_number_reactivated_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWhatsAppNumberReactivatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A number was released and is no longer usable. ### Payload notes Released by you, a billing cleanup or an admin. `reason` is a value such as `user_requested` or `cleanup_suspended`. This is the only terminal status.
pub async fn on_whats_app_number_released(configuration: &configuration::Configuration, on_whats_app_number_released_request: models::OnWhatsAppNumberReleasedRequest) -> Result<(), Error<OnWhatsAppNumberReleasedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_on_whats_app_number_released_request = on_whats_app_number_released_request;
let uri_str = format!("{}/whatsapp.number.released", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_on_whats_app_number_released_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWhatsAppNumberReleasedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// An active number was suspended, for example after a failed payment. ### Payload notes `reason` is a value such as `payment_failed` or `subscription_ended`. The number stops working until the issue is resolved, then `whatsapp.number.reactivated` follows. ### When it does not recover A suspension left unresolved ends in release.
pub async fn on_whats_app_number_suspended(configuration: &configuration::Configuration, on_whats_app_number_suspended_request: models::OnWhatsAppNumberSuspendedRequest) -> Result<(), Error<OnWhatsAppNumberSuspendedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_on_whats_app_number_suspended_request = on_whats_app_number_suspended_request;
let uri_str = format!("{}/whatsapp.number.suspended", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_on_whats_app_number_suspended_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWhatsAppNumberSuspendedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A regulated number requires the end user to complete an identity check. ### Payload notes `verificationUrl` is a one-time link to forward to the person whose ID is on file, for example for Australian mobile numbers. The order completes once they pass. The number stays `pending_regulatory`.
pub async fn on_whats_app_number_verification_required(configuration: &configuration::Configuration, on_whats_app_number_verification_required_request: models::OnWhatsAppNumberVerificationRequiredRequest) -> Result<(), Error<OnWhatsAppNumberVerificationRequiredError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_on_whats_app_number_verification_required_request = on_whats_app_number_verification_required_request;
let uri_str = format!("{}/whatsapp.number.verification_required", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_on_whats_app_number_verification_required_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWhatsAppNumberVerificationRequiredError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// Meta reclassified a WhatsApp template's category, first as a 24-hour advance notice and again when applied. ### When it fires Sent with `template.changeType: \"scheduled\"` for Meta's 24-hour advance notice, and again with `\"applied\"` when the change takes effect. ### Payload notes `template.category` is always the category right now. Meta clears a custom delivery window when it recategorises a template, so read `message_send_ttl_seconds` back after an `applied` change. ### Platform notes Forwarded from Meta's `template_category_update` field. The category decides Meta's per-delivery rate and the delivery window the template can carry.
pub async fn on_whats_app_template_category_updated(configuration: &configuration::Configuration, webhook_payload_whats_app_template_category_updated: models::WebhookPayloadWhatsAppTemplateCategoryUpdated) -> Result<(), Error<OnWhatsAppTemplateCategoryUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_whats_app_template_category_updated = webhook_payload_whats_app_template_category_updated;
let uri_str = format!("{}/whatsapp.template.category_updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_whats_app_template_category_updated);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWhatsAppTemplateCategoryUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// Meta finished reviewing or re-reviewing a WhatsApp Business template on a connected WABA. ### Payload notes Branch on `template.status` (`APPROVED`, `REJECTED`, `PENDING`, `PAUSED`, `DISABLED`, `IN_APPEAL`, `PENDING_DELETION`). `template.reason` is Meta's free-form reason or `\"NONE\"`. ### Platform notes Forwarded from Meta's `message_template_status_update` field. Meta includes neither the previous status nor the template's category.
pub async fn on_whats_app_template_status_updated(configuration: &configuration::Configuration, webhook_payload_whats_app_template_status_updated: models::WebhookPayloadWhatsAppTemplateStatusUpdated) -> Result<(), Error<OnWhatsAppTemplateStatusUpdatedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_whats_app_template_status_updated = webhook_payload_whats_app_template_status_updated;
let uri_str = format!("{}/whatsapp.template.status_updated", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_whats_app_template_status_updated);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWhatsAppTemplateStatusUpdatedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A workflow run ended, with `execution.status` `completed`, or `exited` when it ended on purpose before its last node. ### Exits An exit is a handoff, or a button that switched the contact to another workflow.
pub async fn on_workflow_run_completed(configuration: &configuration::Configuration, webhook_payload_workflow_run: models::WebhookPayloadWorkflowRun) -> Result<(), Error<OnWorkflowRunCompletedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_workflow_run = webhook_payload_workflow_run;
let uri_str = format!("{}/workflow.run.completed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_workflow_run);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWorkflowRunCompletedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A workflow run failed; `error` names the node that failed and why.
pub async fn on_workflow_run_failed(configuration: &configuration::Configuration, webhook_payload_workflow_run: models::WebhookPayloadWorkflowRun) -> Result<(), Error<OnWorkflowRunFailedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_workflow_run = webhook_payload_workflow_run;
let uri_str = format!("{}/workflow.run.failed", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_workflow_run);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWorkflowRunFailedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// A workflow run started for a conversation; `trigger.type` is the trigger node's type. ### Payload notes `trigger.text` is the inbound message that started the run, when there was one.
pub async fn on_workflow_run_started(configuration: &configuration::Configuration, webhook_payload_workflow_run: models::WebhookPayloadWorkflowRun) -> Result<(), Error<OnWorkflowRunStartedError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_body_webhook_payload_workflow_run = webhook_payload_workflow_run;
let uri_str = format!("{}/workflow.run.started", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_body_webhook_payload_workflow_run);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
if !status.is_client_error() && !status.is_server_error() {
Ok(())
} else {
let content = resp.text().await?;
let entity: Option<OnWorkflowRunStartedError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}