late-sdk 0.0.716 → 0.0.718
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +81 -0
- data/docs/AccountsApi.md +142 -1
- data/docs/AdCampaignsApi.md +22 -10
- data/docs/AdCreative.md +2 -0
- data/docs/AdDailyMetrics.md +1 -1
- data/docs/AdEngagementCounts.md +4 -4
- data/docs/AdInsightsApi.md +164 -0
- data/docs/AdMetrics.md +1 -1
- data/docs/AdTargetingApi.md +3 -3
- data/docs/AdTreeCampaign.md +1 -1
- data/docs/AddBroadcastRecipientsRequest.md +1 -1
- data/docs/AnalyticsListResponsePostsInner.md +1 -1
- data/docs/AnalyticsListResponsePostsInnerMediaItemsInner.md +24 -0
- data/docs/AnalyticsSinglePostResponseMediaItemsInner.md +7 -3
- data/docs/BillingSnapshot.md +2 -0
- data/docs/BillingSnapshotPlan.md +3 -1
- data/docs/Blog.md +24 -0
- data/docs/BlogArticle.md +44 -0
- data/docs/BlogArticleImage.md +20 -0
- data/docs/BlogsApi.md +747 -0
- data/docs/BlueskyPlatformData.md +2 -0
- data/docs/BoostPostRequest.md +2 -2
- data/docs/CampaignAnalyticsResponseAnalyticsDailyInner.md +1 -1
- data/docs/CommentsApi.md +8 -8
- data/docs/ConnectApi.md +149 -1
- data/docs/ConnectShopifyWithToken200Response.md +18 -0
- data/docs/ConnectShopifyWithToken200ResponseAccount.md +26 -0
- data/docs/ConnectShopifyWithTokenRequest.md +22 -0
- data/docs/CreateBlog201Response.md +20 -0
- data/docs/CreateBlogArticle201Response.md +20 -0
- data/docs/CreateBlogArticleRequest.md +36 -0
- data/docs/CreateBlogArticleRequestImage.md +20 -0
- data/docs/CreateBlogArticleRequestSeo.md +20 -0
- data/docs/CreateBlogRequest.md +20 -0
- data/docs/CreateCallAdRequest.md +1 -1
- data/docs/CreateInboxConversationRequest.md +2 -0
- data/docs/CreateMessagingAdRequest.md +1 -1
- data/docs/CreatePostRequest.md +1 -1
- data/docs/CreateStandaloneAdRequest.md +10 -6
- data/docs/CreateStandaloneAdRequestPromotedObject.md +2 -2
- data/docs/CreateStandaloneAdRequestVideo.md +1 -1
- data/docs/CtwaAdRequestBody.md +1 -1
- data/docs/ExternalPostMediaItem.md +7 -3
- data/docs/ExternalPostSummary.md +0 -2
- data/docs/ExternalPostSummaryAnalytics.md +1 -1
- data/docs/GetAccountHealth200Response.md +3 -1
- data/docs/GetAccountHealth200ResponsePlatformConnection.md +24 -0
- data/docs/GetAccountHealth200ResponsePlatformConnectionMetaError.md +22 -0
- data/docs/GetAdAnalytics202Response.md +1 -1
- data/docs/GetAdTree202Response.md +1 -1
- data/docs/GetAdsTimeline202Response.md +1 -1
- data/docs/GetBlueskySettings200Response.md +18 -0
- data/docs/GetCampaignAnalytics202Response.md +1 -1
- data/docs/GetInboxPostComments200ResponseCommentsInner.md +4 -2
- data/docs/GetLinkedInPostAnalytics200ResponseAnalytics.md +1 -1
- data/docs/GetPhoneNumberKycForm200Response.md +3 -1
- data/docs/GetWhatsAppNumberKycForm200Response.md +3 -1
- data/docs/LinkedInAggregateAnalyticsTotalResponseAnalytics.md +1 -1
- data/docs/LinkedInPlatformData.md +4 -2
- data/docs/LinkedInPlatformDataPoll.md +22 -0
- data/docs/ListAds202Response.md +1 -1
- data/docs/ListBlogArticles200Response.md +22 -0
- data/docs/ListBlogs200Response.md +22 -0
- data/docs/ListInboxConversations200ResponseDataInnerMetadata.md +3 -3
- data/docs/ListLeads200ResponseLeadsInner.md +3 -3
- data/docs/ListLocalServicesLeadConversations200Response.md +22 -0
- data/docs/ListLocalServicesLeadConversations200ResponseDataInner.md +28 -0
- data/docs/ListLocalServicesLeadConversations200ResponseDataInnerMessage.md +20 -0
- data/docs/ListLocalServicesLeadConversations200ResponseDataInnerPhoneCall.md +20 -0
- data/docs/ListLocalServicesLeads200Response.md +22 -0
- data/docs/ListLocalServicesLeads200ResponseDataInner.md +38 -0
- data/docs/ListLocalServicesLeads200ResponseDataInnerContact.md +22 -0
- data/docs/ListPhoneNumbers200ResponseConnectedInner.md +3 -1
- data/docs/ListPhoneNumbers200ResponseNumbersInner.md +2 -0
- data/docs/ListWhatsAppAccountEvents200Response.md +18 -0
- data/docs/ListWhatsAppAccountEvents200ResponseEventsInner.md +28 -0
- data/docs/MessagesApi.md +4 -4
- data/docs/OnVerificationApprovedRequest.md +1 -1
- data/docs/OnVerificationFailedRequest.md +1 -1
- data/docs/OnWhatsAppAutomaticEventRequest.md +1 -1
- data/docs/OnWhatsAppNumberActionRequiredRequest.md +1 -1
- data/docs/OnWhatsAppNumberActivatedRequest.md +1 -1
- data/docs/OnWhatsAppNumberDeclinedRequest.md +1 -1
- data/docs/OnWhatsAppNumberKycSubmittedRequest.md +1 -1
- data/docs/OnWhatsAppNumberReactivatedRequest.md +1 -1
- data/docs/OnWhatsAppNumberReleasedRequest.md +1 -1
- data/docs/OnWhatsAppNumberSuspendedRequest.md +1 -1
- data/docs/OnWhatsAppNumberVerificationRequiredRequest.md +1 -1
- data/docs/PlatformTarget.md +2 -2
- data/docs/PostAnalytics.md +3 -3
- data/docs/PostsApi.md +1 -1
- data/docs/SMSApi.md +1 -1
- data/docs/SearchAdTargeting200ResponseResultsInner.md +1 -1
- data/docs/SendInboxMessageRequest.md +4 -2
- data/docs/SubmitPhoneNumberKycRequest.md +1 -1
- data/docs/SubmitPhoneNumberKycRequestAddress.md +2 -0
- data/docs/SubmitWhatsAppNumberKycRequest.md +1 -1
- data/docs/TwitterPlatformData.md +2 -0
- data/docs/UpdateAdCampaignStatus200Response.md +6 -6
- data/docs/UpdateAdSet200Response.md +7 -3
- data/docs/UpdateAdSetRequest.md +1 -1
- data/docs/UpdateAdSetStatus200Response.md +9 -3
- data/docs/UpdateBlogArticleRequest.md +36 -0
- data/docs/UpdateBlogRequest.md +20 -0
- data/docs/UpdateBlueskySettingsRequest.md +18 -0
- data/docs/ValidatePhoneNumberKycAddressRequest.md +2 -0
- data/docs/WebhookEventsApi.md +138 -0
- data/docs/WebhookPayloadAccountAdsInitialSyncCompleted.md +1 -1
- data/docs/WebhookPayloadAccountConnected.md +1 -1
- data/docs/WebhookPayloadAccountDisconnected.md +1 -1
- data/docs/WebhookPayloadAdStatusChanged.md +1 -1
- data/docs/WebhookPayloadCallEnded.md +1 -1
- data/docs/WebhookPayloadCallEndedCall.md +4 -0
- data/docs/WebhookPayloadCallFailed.md +1 -1
- data/docs/WebhookPayloadCallPermissionRequest.md +1 -1
- data/docs/WebhookPayloadCallReceived.md +1 -1
- data/docs/WebhookPayloadComment.md +1 -1
- data/docs/WebhookPayloadCommentCommentAuthor.md +2 -0
- data/docs/WebhookPayloadConversationStarted.md +1 -1
- data/docs/WebhookPayloadExternalPost.md +1 -1
- data/docs/WebhookPayloadLead.md +1 -1
- data/docs/WebhookPayloadMessage.md +1 -1
- data/docs/WebhookPayloadMessageDeleted.md +1 -1
- data/docs/WebhookPayloadMessageDeliveryStatus.md +1 -1
- data/docs/WebhookPayloadMessageEdited.md +1 -1
- data/docs/WebhookPayloadMessageMetadata.md +5 -1
- data/docs/WebhookPayloadMessageMetadataReferral.md +5 -3
- data/docs/WebhookPayloadMessageMetadataUnsupported.md +22 -0
- data/docs/WebhookPayloadMessageSent.md +1 -1
- data/docs/WebhookPayloadPost.md +1 -1
- data/docs/WebhookPayloadPostPlatform.md +1 -1
- data/docs/WebhookPayloadReaction.md +1 -1
- data/docs/WebhookPayloadReferral.md +30 -0
- data/docs/WebhookPayloadReferralReferral.md +28 -0
- data/docs/WebhookPayloadReferralReferralAdsContextData.md +28 -0
- data/docs/WebhookPayloadReferralSender.md +20 -0
- data/docs/WebhookPayloadReviewNew.md +1 -1
- data/docs/WebhookPayloadReviewUpdated.md +1 -1
- data/docs/WebhookPayloadTest.md +1 -1
- data/docs/WebhookPayloadWhatsAppTemplateCategoryUpdated.md +26 -0
- data/docs/WebhookPayloadWhatsAppTemplateCategoryUpdatedTemplate.md +32 -0
- data/docs/WebhookPayloadWhatsAppTemplateStatusUpdated.md +1 -1
- data/docs/WhatsAppApi.md +74 -0
- data/docs/WorkflowNode.md +3 -1
- data/docs/XArticle.md +24 -0
- data/docs/XArticleBlock.md +28 -0
- data/docs/XArticleBlockData.md +24 -0
- data/docs/XArticleContentState.md +20 -0
- data/docs/XArticleCover.md +20 -0
- data/docs/XArticleEntity.md +57 -0
- data/docs/XArticleEntityOneOf.md +20 -0
- data/docs/XArticleEntityOneOf1.md +20 -0
- data/docs/XArticleEntityOneOf1Value.md +22 -0
- data/docs/XArticleEntityOneOf1ValueData.md +18 -0
- data/docs/XArticleEntityOneOf2.md +20 -0
- data/docs/XArticleEntityOneOf2Value.md +22 -0
- data/docs/XArticleEntityOneOf2ValueData.md +22 -0
- data/docs/XArticleEntityOneOf3.md +20 -0
- data/docs/XArticleEntityOneOf3Value.md +22 -0
- data/docs/XArticleEntityOneOf3ValueData.md +18 -0
- data/docs/XArticleEntityOneOf4.md +20 -0
- data/docs/XArticleEntityOneOf4Value.md +22 -0
- data/docs/XArticleEntityOneOf4ValueData.md +18 -0
- data/docs/XArticleEntityOneOf5.md +20 -0
- data/docs/XArticleEntityOneOf5Value.md +22 -0
- data/docs/XArticleEntityOneOfValue.md +22 -0
- data/docs/XArticleEntityOneOfValueData.md +18 -0
- data/docs/XArticleEntityRange.md +22 -0
- data/docs/XArticleInlineStyleRange.md +22 -0
- data/docs/XArticleTextRange.md +22 -0
- data/docs/YouTubeVideoRetentionResponse.md +1 -1
- data/docs/YouTubeVideoRetentionResponseRetentionCurveInner.md +2 -2
- data/lib/zernio-sdk/api/accounts_api.rb +139 -2
- data/lib/zernio-sdk/api/ad_campaigns_api.rb +35 -8
- data/lib/zernio-sdk/api/ad_insights_api.rb +165 -0
- data/lib/zernio-sdk/api/ad_targeting_api.rb +5 -5
- data/lib/zernio-sdk/api/blogs_api.rb +845 -0
- data/lib/zernio-sdk/api/comments_api.rb +10 -10
- data/lib/zernio-sdk/api/connect_api.rb +149 -0
- data/lib/zernio-sdk/api/messages_api.rb +4 -4
- data/lib/zernio-sdk/api/posts_api.rb +2 -2
- data/lib/zernio-sdk/api/sms_api.rb +2 -2
- data/lib/zernio-sdk/api/webhook_events_api.rb +132 -0
- data/lib/zernio-sdk/api/whats_app_api.rb +75 -0
- data/lib/zernio-sdk/models/account_with_follower_stats.rb +2 -2
- data/lib/zernio-sdk/models/ad_creative.rb +12 -1
- data/lib/zernio-sdk/models/ad_daily_metrics.rb +1 -1
- data/lib/zernio-sdk/models/ad_engagement_counts.rb +5 -5
- data/lib/zernio-sdk/models/ad_metrics.rb +1 -1
- data/lib/zernio-sdk/models/ad_tree_campaign.rb +1 -1
- data/lib/zernio-sdk/models/add_broadcast_recipients_request.rb +1 -1
- data/lib/zernio-sdk/models/analytics_list_response_posts_inner.rb +1 -1
- data/lib/zernio-sdk/models/analytics_list_response_posts_inner_media_items_inner.rb +211 -0
- data/lib/zernio-sdk/models/analytics_single_post_response_media_items_inner.rb +52 -6
- data/lib/zernio-sdk/models/billing_snapshot.rb +14 -3
- data/lib/zernio-sdk/models/billing_snapshot_plan.rb +14 -4
- data/lib/zernio-sdk/models/blog.rb +211 -0
- data/lib/zernio-sdk/models/blog_article.rb +315 -0
- data/lib/zernio-sdk/models/blog_article_image.rb +158 -0
- data/lib/zernio-sdk/models/bluesky_platform_data.rb +42 -2
- data/lib/zernio-sdk/models/boost_post_request.rb +30 -1
- data/lib/zernio-sdk/models/campaign_analytics_response_analytics_daily_inner.rb +1 -1
- data/lib/zernio-sdk/models/connect_shopify_with_token200_response.rb +147 -0
- data/lib/zernio-sdk/models/connect_shopify_with_token200_response_account.rb +218 -0
- data/lib/zernio-sdk/models/connect_shopify_with_token_request.rb +219 -0
- data/lib/zernio-sdk/models/create_blog201_response.rb +190 -0
- data/lib/zernio-sdk/models/create_blog_article201_response.rb +190 -0
- data/lib/zernio-sdk/models/create_blog_article_request.rb +262 -0
- data/lib/zernio-sdk/models/create_blog_article_request_image.rb +174 -0
- data/lib/zernio-sdk/models/create_blog_article_request_seo.rb +157 -0
- data/lib/zernio-sdk/models/create_blog_request.rb +202 -0
- data/lib/zernio-sdk/models/create_call_ad_request.rb +1 -1
- data/lib/zernio-sdk/models/create_inbox_conversation_request.rb +13 -1
- data/lib/zernio-sdk/models/create_messaging_ad_request.rb +1 -1
- data/lib/zernio-sdk/models/create_post_request.rb +1 -1
- data/lib/zernio-sdk/models/create_standalone_ad_request.rb +67 -6
- data/lib/zernio-sdk/models/create_standalone_ad_request_creatives_inner_video.rb +1 -1
- data/lib/zernio-sdk/models/create_standalone_ad_request_promoted_object.rb +3 -3
- data/lib/zernio-sdk/models/create_standalone_ad_request_video.rb +1 -1
- data/lib/zernio-sdk/models/ctwa_ad_request_body.rb +1 -1
- data/lib/zernio-sdk/models/external_post_media_item.rb +48 -16
- data/lib/zernio-sdk/models/external_post_summary.rb +1 -11
- data/lib/zernio-sdk/models/external_post_summary_analytics.rb +1 -0
- data/lib/zernio-sdk/models/facebook_settings.rb +5 -5
- data/lib/zernio-sdk/models/get_account_health200_response.rb +13 -4
- data/lib/zernio-sdk/models/get_account_health200_response_platform_connection.rb +213 -0
- data/lib/zernio-sdk/models/get_account_health200_response_platform_connection_meta_error.rb +168 -0
- data/lib/zernio-sdk/models/get_ad_analytics202_response.rb +6 -29
- data/lib/zernio-sdk/models/get_ad_tree202_response.rb +6 -29
- data/lib/zernio-sdk/models/get_ads_timeline202_response.rb +6 -29
- data/lib/zernio-sdk/models/get_bluesky_settings200_response.rb +150 -0
- data/lib/zernio-sdk/models/get_campaign_analytics202_response.rb +6 -29
- data/lib/zernio-sdk/models/get_inbox_post_comments200_response_comments_inner.rb +13 -2
- data/lib/zernio-sdk/models/get_linked_in_post_analytics200_response_analytics.rb +1 -1
- data/lib/zernio-sdk/models/get_phone_number_kyc_form200_response.rb +14 -4
- data/lib/zernio-sdk/models/get_whats_app_number_kyc_form200_response.rb +14 -4
- data/lib/zernio-sdk/models/inbox_webhook_message.rb +2 -2
- data/lib/zernio-sdk/models/linked_in_aggregate_analytics_total_response_analytics.rb +1 -1
- data/lib/zernio-sdk/models/linked_in_platform_data.rb +15 -6
- data/lib/zernio-sdk/models/linked_in_platform_data_poll.rb +277 -0
- data/lib/zernio-sdk/models/list_ads202_response.rb +6 -29
- data/lib/zernio-sdk/models/list_blog_articles200_response.rb +203 -0
- data/lib/zernio-sdk/models/list_blogs200_response.rb +203 -0
- data/lib/zernio-sdk/models/list_broadcast_recipients200_response_recipients_inner.rb +1 -0
- data/lib/zernio-sdk/models/list_inbox_conversations200_response_data_inner_metadata.rb +4 -4
- data/lib/zernio-sdk/models/list_leads200_response_leads_inner.rb +3 -2
- data/lib/zernio-sdk/models/list_local_services_lead_conversations200_response.rb +167 -0
- data/lib/zernio-sdk/models/list_local_services_lead_conversations200_response_data_inner.rb +198 -0
- data/lib/zernio-sdk/models/list_local_services_lead_conversations200_response_data_inner_message.rb +160 -0
- data/lib/zernio-sdk/models/list_local_services_lead_conversations200_response_data_inner_phone_call.rb +159 -0
- data/lib/zernio-sdk/models/list_local_services_leads200_response.rb +167 -0
- data/lib/zernio-sdk/models/list_local_services_leads200_response_data_inner.rb +249 -0
- data/lib/zernio-sdk/models/list_local_services_leads200_response_data_inner_contact.rb +169 -0
- data/lib/zernio-sdk/models/list_phone_numbers200_response_connected_inner.rb +15 -5
- data/lib/zernio-sdk/models/list_phone_numbers200_response_numbers_inner.rb +11 -1
- data/lib/zernio-sdk/models/list_sequence_enrollments200_response_enrollments_inner.rb +3 -0
- data/lib/zernio-sdk/models/list_whats_app_account_events200_response.rb +149 -0
- data/lib/zernio-sdk/models/list_whats_app_account_events200_response_events_inner.rb +228 -0
- data/lib/zernio-sdk/models/on_verification_approved_request.rb +1 -0
- data/lib/zernio-sdk/models/on_verification_failed_request.rb +1 -0
- data/lib/zernio-sdk/models/on_whats_app_automatic_event_request.rb +1 -0
- data/lib/zernio-sdk/models/on_whats_app_number_action_required_request.rb +1 -0
- data/lib/zernio-sdk/models/on_whats_app_number_activated_request.rb +1 -0
- data/lib/zernio-sdk/models/on_whats_app_number_declined_request.rb +1 -0
- data/lib/zernio-sdk/models/on_whats_app_number_kyc_submitted_request.rb +1 -0
- data/lib/zernio-sdk/models/on_whats_app_number_reactivated_request.rb +1 -0
- data/lib/zernio-sdk/models/on_whats_app_number_released_request.rb +1 -0
- data/lib/zernio-sdk/models/on_whats_app_number_suspended_request.rb +1 -0
- data/lib/zernio-sdk/models/on_whats_app_number_verification_required_request.rb +1 -0
- data/lib/zernio-sdk/models/platform_target.rb +5 -4
- data/lib/zernio-sdk/models/post_analytics.rb +2 -1
- data/lib/zernio-sdk/models/search_ad_targeting200_response_results_inner.rb +1 -1
- data/lib/zernio-sdk/models/send_inbox_message_request.rb +15 -3
- data/lib/zernio-sdk/models/social_account.rb +2 -2
- data/lib/zernio-sdk/models/submit_phone_number_kyc_request.rb +1 -1
- data/lib/zernio-sdk/models/submit_phone_number_kyc_request_address.rb +11 -1
- data/lib/zernio-sdk/models/submit_whats_app_number_kyc_request.rb +1 -1
- data/lib/zernio-sdk/models/twitter_platform_data.rb +11 -2
- data/lib/zernio-sdk/models/update_ad_campaign_status200_response.rb +50 -15
- data/lib/zernio-sdk/models/update_ad_set200_response.rb +26 -1
- data/lib/zernio-sdk/models/update_ad_set_request.rb +1 -1
- data/lib/zernio-sdk/models/update_ad_set_status200_response.rb +72 -4
- data/lib/zernio-sdk/models/update_blog_article_request.rb +257 -0
- data/lib/zernio-sdk/models/update_blog_request.rb +196 -0
- data/lib/zernio-sdk/models/update_bluesky_settings_request.rb +176 -0
- data/lib/zernio-sdk/models/validate_phone_number_kyc_address_request.rb +11 -1
- data/lib/zernio-sdk/models/webhook_payload_account_ads_initial_sync_completed.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_account_connected.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_account_disconnected.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_ad_status_changed.rb +1 -1
- data/lib/zernio-sdk/models/webhook_payload_call_ended.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_call_ended_call.rb +23 -1
- data/lib/zernio-sdk/models/webhook_payload_call_failed.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_call_permission_request.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_call_received.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_comment.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_comment_comment_author.rb +11 -1
- data/lib/zernio-sdk/models/webhook_payload_conversation_started.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_external_post.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_lead.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_message.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_message_deleted.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_message_delivery_status.rb +2 -1
- data/lib/zernio-sdk/models/webhook_payload_message_edited.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_message_message.rb +2 -2
- data/lib/zernio-sdk/models/webhook_payload_message_metadata.rb +23 -4
- data/lib/zernio-sdk/models/webhook_payload_message_metadata_referral.rb +15 -5
- data/lib/zernio-sdk/models/webhook_payload_message_metadata_unsupported.rb +169 -0
- data/lib/zernio-sdk/models/webhook_payload_message_sent.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_post.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_post_platform.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_reaction.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_reaction_reaction_sender.rb +1 -1
- data/lib/zernio-sdk/models/webhook_payload_referral.rb +347 -0
- data/lib/zernio-sdk/models/webhook_payload_referral_referral.rb +198 -0
- data/lib/zernio-sdk/models/webhook_payload_referral_referral_ads_context_data.rb +193 -0
- data/lib/zernio-sdk/models/webhook_payload_referral_sender.rb +176 -0
- data/lib/zernio-sdk/models/webhook_payload_review_new.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_review_updated.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_test.rb +1 -0
- data/lib/zernio-sdk/models/webhook_payload_whats_app_template_category_updated.rb +295 -0
- data/lib/zernio-sdk/models/webhook_payload_whats_app_template_category_updated_template.rb +353 -0
- data/lib/zernio-sdk/models/webhook_payload_whats_app_template_status_updated.rb +1 -1
- data/lib/zernio-sdk/models/workflow_node.rb +42 -4
- data/lib/zernio-sdk/models/x_article.rb +255 -0
- data/lib/zernio-sdk/models/x_article_block.rb +273 -0
- data/lib/zernio-sdk/models/x_article_block_data.rb +182 -0
- data/lib/zernio-sdk/models/x_article_content_state.rb +204 -0
- data/lib/zernio-sdk/models/x_article_cover.rb +204 -0
- data/lib/zernio-sdk/models/x_article_entity.rb +109 -0
- data/lib/zernio-sdk/models/x_article_entity_one_of.rb +199 -0
- data/lib/zernio-sdk/models/x_article_entity_one_of1.rb +199 -0
- data/lib/zernio-sdk/models/x_article_entity_one_of1_value.rb +242 -0
- data/lib/zernio-sdk/models/x_article_entity_one_of1_value_data.rb +164 -0
- data/lib/zernio-sdk/models/x_article_entity_one_of2.rb +199 -0
- data/lib/zernio-sdk/models/x_article_entity_one_of2_value.rb +242 -0
- data/lib/zernio-sdk/models/x_article_entity_one_of2_value_data.rb +214 -0
- data/lib/zernio-sdk/models/x_article_entity_one_of3.rb +199 -0
- data/lib/zernio-sdk/models/x_article_entity_one_of3_value.rb +242 -0
- data/lib/zernio-sdk/models/x_article_entity_one_of3_value_data.rb +173 -0
- data/lib/zernio-sdk/models/x_article_entity_one_of4.rb +199 -0
- data/lib/zernio-sdk/models/x_article_entity_one_of4_value.rb +242 -0
- data/lib/zernio-sdk/models/x_article_entity_one_of4_value_data.rb +164 -0
- data/lib/zernio-sdk/models/x_article_entity_one_of5.rb +199 -0
- data/lib/zernio-sdk/models/x_article_entity_one_of5_value.rb +242 -0
- data/lib/zernio-sdk/models/x_article_entity_one_of_value.rb +242 -0
- data/lib/zernio-sdk/models/x_article_entity_one_of_value_data.rb +173 -0
- data/lib/zernio-sdk/models/x_article_entity_range.rb +245 -0
- data/lib/zernio-sdk/models/x_article_inline_style_range.rb +259 -0
- data/lib/zernio-sdk/models/x_article_text_range.rb +237 -0
- data/lib/zernio-sdk/models/you_tube_video_retention_response.rb +1 -1
- data/lib/zernio-sdk/models/you_tube_video_retention_response_retention_curve_inner.rb +2 -2
- data/lib/zernio-sdk/version.rb +1 -1
- data/lib/zernio-sdk.rb +65 -0
- data/openapi.yaml +1956 -165
- data/spec/api/accounts_api_spec.rb +26 -1
- data/spec/api/ad_campaigns_api_spec.rb +9 -4
- data/spec/api/ad_insights_api_spec.rb +34 -0
- data/spec/api/ad_targeting_api_spec.rb +2 -2
- data/spec/api/blogs_api_spec.rb +174 -0
- data/spec/api/comments_api_spec.rb +5 -5
- data/spec/api/connect_api_spec.rb +27 -0
- data/spec/api/messages_api_spec.rb +2 -2
- data/spec/api/posts_api_spec.rb +1 -1
- data/spec/api/sms_api_spec.rb +1 -1
- data/spec/api/whats_app_api_spec.rb +13 -0
- data/spec/models/account_with_follower_stats_spec.rb +1 -1
- data/spec/models/ad_creative_spec.rb +6 -0
- data/spec/models/analytics_list_response_posts_inner_media_items_inner_spec.rb +58 -0
- data/spec/models/analytics_single_post_response_media_items_inner_spec.rb +20 -0
- data/spec/models/billing_snapshot_plan_spec.rb +6 -0
- data/spec/models/billing_snapshot_spec.rb +7 -1
- data/spec/models/blog_article_image_spec.rb +42 -0
- data/spec/models/blog_article_spec.rb +118 -0
- data/spec/models/blog_spec.rb +58 -0
- data/spec/models/bluesky_platform_data_spec.rb +6 -0
- data/spec/models/connect_shopify_with_token200_response_account_spec.rb +64 -0
- data/spec/models/connect_shopify_with_token200_response_spec.rb +36 -0
- data/spec/models/connect_shopify_with_token_request_spec.rb +48 -0
- data/spec/models/create_blog201_response_spec.rb +46 -0
- data/spec/models/create_blog_article201_response_spec.rb +46 -0
- data/spec/models/create_blog_article_request_image_spec.rb +42 -0
- data/spec/models/create_blog_article_request_seo_spec.rb +42 -0
- data/spec/models/create_blog_article_request_spec.rb +90 -0
- data/spec/models/create_blog_request_spec.rb +42 -0
- data/spec/models/create_inbox_conversation_request_spec.rb +6 -0
- data/spec/models/create_standalone_ad_request_spec.rb +16 -0
- data/spec/models/create_webhook_settings_request_spec.rb +1 -1
- data/spec/models/external_post_media_item_spec.rb +20 -0
- data/spec/models/external_post_summary_spec.rb +0 -6
- data/spec/models/get_account_health200_response_platform_connection_meta_error_spec.rb +48 -0
- data/spec/models/get_account_health200_response_platform_connection_spec.rb +58 -0
- data/spec/models/get_account_health200_response_spec.rb +6 -0
- data/spec/models/get_ad_analytics202_response_spec.rb +0 -4
- data/spec/models/get_ad_tree202_response_spec.rb +0 -4
- data/spec/models/get_ads_timeline202_response_spec.rb +0 -4
- data/spec/models/get_bluesky_settings200_response_spec.rb +36 -0
- data/spec/models/get_campaign_analytics202_response_spec.rb +0 -4
- data/spec/models/get_inbox_post_comments200_response_comments_inner_spec.rb +6 -0
- data/spec/models/get_phone_number_kyc_form200_response_spec.rb +6 -0
- data/spec/models/get_whats_app_number_kyc_form200_response_spec.rb +6 -0
- data/spec/models/inbox_webhook_message_spec.rb +1 -1
- data/spec/models/linked_in_platform_data_poll_spec.rb +52 -0
- data/spec/models/linked_in_platform_data_spec.rb +6 -0
- data/spec/models/list_ads202_response_spec.rb +0 -4
- data/spec/models/list_blog_articles200_response_spec.rb +52 -0
- data/spec/models/list_blogs200_response_spec.rb +52 -0
- data/spec/models/list_local_services_lead_conversations200_response_data_inner_message_spec.rb +42 -0
- data/spec/models/list_local_services_lead_conversations200_response_data_inner_phone_call_spec.rb +42 -0
- data/spec/models/list_local_services_lead_conversations200_response_data_inner_spec.rb +66 -0
- data/spec/models/list_local_services_lead_conversations200_response_spec.rb +48 -0
- data/spec/models/list_local_services_leads200_response_data_inner_contact_spec.rb +48 -0
- data/spec/models/list_local_services_leads200_response_data_inner_spec.rb +96 -0
- data/spec/models/list_local_services_leads200_response_spec.rb +48 -0
- data/spec/models/list_phone_numbers200_response_connected_inner_spec.rb +6 -0
- data/spec/models/list_phone_numbers200_response_numbers_inner_spec.rb +6 -0
- data/spec/models/list_whats_app_account_events200_response_events_inner_spec.rb +70 -0
- data/spec/models/list_whats_app_account_events200_response_spec.rb +36 -0
- data/spec/models/platform_target_spec.rb +1 -1
- data/spec/models/send_inbox_message_request_spec.rb +6 -0
- data/spec/models/social_account_spec.rb +1 -1
- data/spec/models/submit_phone_number_kyc_request_address_spec.rb +6 -0
- data/spec/models/twitter_platform_data_spec.rb +6 -0
- data/spec/models/update_ad_campaign_status200_response_spec.rb +8 -4
- data/spec/models/update_ad_set200_response_spec.rb +12 -0
- data/spec/models/update_ad_set_status200_response_spec.rb +22 -0
- data/spec/models/update_blog_article_request_spec.rb +90 -0
- data/spec/models/update_blog_request_spec.rb +42 -0
- data/spec/models/update_bluesky_settings_request_spec.rb +36 -0
- data/spec/models/update_webhook_settings_request_spec.rb +1 -1
- data/spec/models/validate_phone_number_kyc_address_request_spec.rb +6 -0
- data/spec/models/webhook_payload_call_ended_call_spec.rb +12 -0
- data/spec/models/webhook_payload_comment_comment_author_spec.rb +6 -0
- data/spec/models/webhook_payload_message_message_spec.rb +1 -1
- data/spec/models/webhook_payload_message_metadata_referral_spec.rb +6 -0
- data/spec/models/webhook_payload_message_metadata_spec.rb +12 -0
- data/spec/models/webhook_payload_message_metadata_unsupported_spec.rb +48 -0
- data/spec/models/webhook_payload_referral_referral_ads_context_data_spec.rb +66 -0
- data/spec/models/webhook_payload_referral_referral_spec.rb +66 -0
- data/spec/models/webhook_payload_referral_sender_spec.rb +42 -0
- data/spec/models/webhook_payload_referral_spec.rb +76 -0
- data/spec/models/webhook_payload_whats_app_template_category_updated_spec.rb +64 -0
- data/spec/models/webhook_payload_whats_app_template_category_updated_template_spec.rb +94 -0
- data/spec/models/webhook_spec.rb +1 -1
- data/spec/models/workflow_node_spec.rb +6 -0
- data/spec/models/x_article_block_data_spec.rb +54 -0
- data/spec/models/x_article_block_spec.rb +70 -0
- data/spec/models/x_article_content_state_spec.rb +42 -0
- data/spec/models/x_article_cover_spec.rb +42 -0
- data/spec/models/x_article_entity_one_of1_spec.rb +42 -0
- data/spec/models/x_article_entity_one_of1_value_data_spec.rb +36 -0
- data/spec/models/x_article_entity_one_of1_value_spec.rb +56 -0
- data/spec/models/x_article_entity_one_of2_spec.rb +42 -0
- data/spec/models/x_article_entity_one_of2_value_data_spec.rb +48 -0
- data/spec/models/x_article_entity_one_of2_value_spec.rb +56 -0
- data/spec/models/x_article_entity_one_of3_spec.rb +42 -0
- data/spec/models/x_article_entity_one_of3_value_data_spec.rb +36 -0
- data/spec/models/x_article_entity_one_of3_value_spec.rb +56 -0
- data/spec/models/x_article_entity_one_of4_spec.rb +42 -0
- data/spec/models/x_article_entity_one_of4_value_data_spec.rb +36 -0
- data/spec/models/x_article_entity_one_of4_value_spec.rb +56 -0
- data/spec/models/x_article_entity_one_of5_spec.rb +42 -0
- data/spec/models/x_article_entity_one_of5_value_spec.rb +56 -0
- data/spec/models/x_article_entity_one_of_spec.rb +42 -0
- data/spec/models/x_article_entity_one_of_value_data_spec.rb +36 -0
- data/spec/models/x_article_entity_one_of_value_spec.rb +56 -0
- data/spec/models/x_article_entity_range_spec.rb +48 -0
- data/spec/models/x_article_entity_spec.rb +32 -0
- data/spec/models/x_article_inline_style_range_spec.rb +52 -0
- data/spec/models/x_article_spec.rb +58 -0
- data/spec/models/x_article_text_range_spec.rb +48 -0
- data/zernio-sdk-0.0.718.gem +0 -0
- metadata +1867 -1607
- data/zernio-sdk-0.0.716.gem +0 -0
data/openapi.yaml
CHANGED
|
@@ -150,21 +150,23 @@ x-documentation:
|
|
|
150
150
|
- `account.connected` - Social account connected
|
|
151
151
|
- `account.disconnected` - Social account disconnected (token expired)
|
|
152
152
|
- `account.ads.initial_sync_completed` - Initial ads sync (discovery + 90-day backfill) completed for an ads-enabled account
|
|
153
|
-
- `message.received` - New DM received
|
|
154
|
-
- `conversation.started` - A new conversation opened between one of your accounts and a contact, in either direction (any DM platform); fires only the first time the thread appears
|
|
153
|
+
- `message.received` - New inbound DM or SMS received (SMS arrives with `platform: "sms"`)
|
|
154
|
+
- `conversation.started` - A new conversation opened between one of your accounts and a contact, in either direction (any DM platform, and SMS); fires only the first time the thread appears
|
|
155
155
|
- `message.sent` - DM sent via the API
|
|
156
156
|
- `message.edited` - A sender edited a message (Instagram, Messenger, Telegram)
|
|
157
157
|
- `message.deleted` - A sender deleted ("unsent") a message (Instagram; WhatsApp when the business deletes a sent message)
|
|
158
|
-
- `message.delivered` - An outgoing message was delivered (WhatsApp, Messenger)
|
|
158
|
+
- `message.delivered` - An outgoing message was delivered (WhatsApp, Messenger, SMS)
|
|
159
159
|
- `message.read` - An outgoing message was read by the recipient (WhatsApp, Messenger, Instagram)
|
|
160
|
-
- `message.failed` - An outgoing message failed delivery (WhatsApp)
|
|
160
|
+
- `message.failed` - An outgoing message failed delivery (WhatsApp, SMS; on SMS the carrier's error code rides in `error`)
|
|
161
161
|
- `reaction.received` - A participant added or removed an emoji reaction on a message (WhatsApp, Telegram, Slack, Instagram, Facebook Messenger)
|
|
162
|
+
- `referral.received` - Someone opened an existing Instagram/Messenger thread through an ig.me/m.me `ref` link or a returning Messenger ad click; carries Meta's referral object (a referral that rides an inbound message arrives on `message.received` under `metadata.referral` instead)
|
|
162
163
|
- `comment.received` - New comment received on a post
|
|
163
164
|
- `review.new` - New review posted on a connected account (Google Business Profile)
|
|
164
165
|
- `review.updated` - Review updated or reply added (Google Business Profile, or via reply API)
|
|
165
166
|
- `lead.received` - New lead submitted against a Meta Lead Gen (Instant) Form. `lead.fields` is the question-key → answer map; `lead.formId`/`lead.adId` give provenance.
|
|
166
167
|
- `ad.status_changed` - Ad, ad set, or campaign changed status on the ad platform (Meta: `in_process_ad_objects` entry/exit and `with_issues_ad_objects` violations)
|
|
167
168
|
- `whatsapp.template.status_updated` - WhatsApp Business template completed (re)review by Meta. `template.status` carries the new state (APPROVED, REJECTED, PENDING, PAUSED, DISABLED, IN_APPEAL, PENDING_DELETION); `template.reason` is Meta's free-form reason or "NONE".
|
|
169
|
+
- `whatsapp.template.category_updated` - Meta reclassified a WhatsApp Business template's category (drives tariff and marketing opt-out applicability). `template.changeType` is `scheduled` (24h advance notice) or `applied`; `template.category` is always the category right now.
|
|
168
170
|
- `call.received` - An inbound call (phone/PSTN or WhatsApp) reached one of your numbers and was routed to its destination
|
|
169
171
|
- `call.ended` - A call ended; carries duration, end reason, cost breakdown, and the recording when enabled
|
|
170
172
|
- `call.failed` - A call failed with a hard error before or during bridging
|
|
@@ -201,6 +203,12 @@ tags:
|
|
|
201
203
|
- name: Posts
|
|
202
204
|
description: |
|
|
203
205
|
Create, schedule, list, update, and delete posts across all connected social accounts.
|
|
206
|
+
- name: Blogs
|
|
207
|
+
description: |
|
|
208
|
+
Manage blogs and blog articles on connected accounts. Currently supported
|
|
209
|
+
for Shopify accounts (scopes read_content and write_content). Blogs are
|
|
210
|
+
the containers; articles are the posts inside them. All content lives on
|
|
211
|
+
the platform; Zernio proxies it and stores nothing.
|
|
204
212
|
- name: Users
|
|
205
213
|
description: |
|
|
206
214
|
Read the authenticated user and team members.
|
|
@@ -412,7 +420,7 @@ tags:
|
|
|
412
420
|
- name: Webhooks
|
|
413
421
|
description: |
|
|
414
422
|
Configure webhooks for real-time notifications. Webhooks can be created from the dashboard (Settings → Webhooks) or via this API.
|
|
415
|
-
Events: post.scheduled, post.published, post.failed, post.partial, post.cancelled, post.recycled, post.platform.published, post.platform.failed, post.platform.deleted, post.tiktok.url_resolved, post.external.created, post.external.updated, post.external.deleted, account.connected, account.disconnected, account.ads.initial_sync_completed, message.received, conversation.started, call.received, call.ended, call.failed, call.permission_request, message.sent, message.edited, message.deleted, message.delivered, message.read, message.failed, reaction.received, comment.received, review.new, review.updated, lead.received, ad.status_changed, whatsapp.template.status_updated, whatsapp.automatic_event, whatsapp.number.activated, whatsapp.number.declined, whatsapp.number.action_required, whatsapp.number.verification_required, whatsapp.number.suspended, whatsapp.number.reactivated, whatsapp.number.released, whatsapp.number.kyc_submitted, verification.approved, verification.failed, webhook.test.
|
|
423
|
+
Events: post.scheduled, post.published, post.failed, post.partial, post.cancelled, post.recycled, post.platform.published, post.platform.failed, post.platform.deleted, post.tiktok.url_resolved, post.external.created, post.external.updated, post.external.deleted, account.connected, account.disconnected, account.ads.initial_sync_completed, message.received, conversation.started, call.received, call.ended, call.failed, call.permission_request, message.sent, message.edited, message.deleted, message.delivered, message.read, message.failed, reaction.received, referral.received, comment.received, review.new, review.updated, lead.received, ad.status_changed, whatsapp.template.status_updated, whatsapp.template.category_updated, whatsapp.automatic_event, whatsapp.number.activated, whatsapp.number.declined, whatsapp.number.action_required, whatsapp.number.verification_required, whatsapp.number.suspended, whatsapp.number.reactivated, whatsapp.number.released, whatsapp.number.kyc_submitted, verification.approved, verification.failed, webhook.test.
|
|
416
424
|
Security: optional HMAC-SHA256 signature in X-Zernio-Signature header. Configure a secret key to enable verification. Custom headers supported.
|
|
417
425
|
|
|
418
426
|
Resource groups. Every event belongs to one group: post.* to publishing, message.*, reaction.*, conversation.*, call.* and whatsapp.automatic_event to messages, comment.* and review.* to engagement, lead.* to contacts, ad.* to ads, account.* and whatsapp.template.* to accounts, whatsapp.number.* and verification.* to telephony, webhook.test to webhooks. Two independent controls use that mapping. (1) A restricted (zrk_) API key can only subscribe to, test-fire, redeliver, or read delivery logs for events in the groups it holds, so it can never create a subscription broader than itself. (2) Each subscription carries its own `disabledResourceGroups` denylist: events in a disabled group are dropped before delivery to that endpoint, on live delivery and on every replay path, no matter which key or session created the subscription. Changing that denylist applies to every event emitted after the change; events already queued when it landed can still be delivered for up to five minutes after they were enqueued, because the delivery worker trusts a five-minute enqueue-time snapshot before re-checking. Absent or empty on a subscription means it receives everything it subscribes to, which is the behavior of every subscription created before the field existed.
|
|
@@ -892,8 +900,11 @@ components:
|
|
|
892
900
|
maxLength: 3
|
|
893
901
|
description: |
|
|
894
902
|
ISO 4217 currency code matching the ad account's currency
|
|
895
|
-
(e.g. `USD`). Optional
|
|
896
|
-
when omitted.
|
|
903
|
+
(e.g. `USD`). Optional: Zernio resolves it from the ad account
|
|
904
|
+
when omitted. The value selects the minor-unit exponent Zernio
|
|
905
|
+
converts budget/bid amounts by before calling Meta (most
|
|
906
|
+
currencies are cents; zero-decimal currencies like JPY/KRW are
|
|
907
|
+
sent as-is).
|
|
897
908
|
endDate:
|
|
898
909
|
type: string
|
|
899
910
|
format: date-time
|
|
@@ -1197,6 +1208,11 @@ components:
|
|
|
1197
1208
|
properties:
|
|
1198
1209
|
x: { type: number }
|
|
1199
1210
|
y: { type: number }
|
|
1211
|
+
label:
|
|
1212
|
+
type: string
|
|
1213
|
+
minLength: 1
|
|
1214
|
+
maxLength: 80
|
|
1215
|
+
description: 'Optional display name shown on the builder canvas and inspector, falling back to the node type when absent. The nodes array is replaced wholesale on update, so it must be resent to be kept.'
|
|
1200
1216
|
WorkflowEdge:
|
|
1201
1217
|
type: object
|
|
1202
1218
|
required: [id, source, target]
|
|
@@ -1352,9 +1368,6 @@ components:
|
|
|
1352
1368
|
mediaType:
|
|
1353
1369
|
type: string
|
|
1354
1370
|
description: Media type (e.g. image, video, carousel)
|
|
1355
|
-
mediaUrl:
|
|
1356
|
-
type: string
|
|
1357
|
-
description: Primary media URL
|
|
1358
1371
|
thumbnailUrl:
|
|
1359
1372
|
type: string
|
|
1360
1373
|
description: Thumbnail URL
|
|
@@ -1381,7 +1394,7 @@ components:
|
|
|
1381
1394
|
views: { type: integer }
|
|
1382
1395
|
reach: { type: integer }
|
|
1383
1396
|
impressions: { type: integer }
|
|
1384
|
-
engagementRate: { type: number }
|
|
1397
|
+
engagementRate: { type: number, description: 'Percentage, rounded to 2 decimals. Same definition as PostAnalytics.engagementRate: (likes + comments + shares + saves) / (impressions or reach or views) * 100, where the denominator is the first of the three that is non-zero. Clicks and follows are never counted.' }
|
|
1385
1398
|
lastUpdated: { type: string, format: date-time, description: When these metrics were last refreshed }
|
|
1386
1399
|
ErrorResponse:
|
|
1387
1400
|
type: object
|
|
@@ -1943,7 +1956,7 @@ components:
|
|
|
1943
1956
|
description: 'Present only when the range reaches into YouTube''s ~3-day processing window: the first date whose numbers are provisional and may still be revised by YouTube.'
|
|
1944
1957
|
retentionCurve:
|
|
1945
1958
|
type: array
|
|
1946
|
-
description: Up to 100 points covering the video timeline, aggregated over the date range.
|
|
1959
|
+
description: 'Up to 100 points covering the video timeline, aggregated over the date range. Can be empty when YouTube has no retention data for the video in the given range.'
|
|
1947
1960
|
items:
|
|
1948
1961
|
type: object
|
|
1949
1962
|
properties:
|
|
@@ -1958,10 +1971,10 @@ components:
|
|
|
1958
1971
|
description: Retention vs videos of similar length (0 = worst, 0.5 = median, 1 = best)
|
|
1959
1972
|
startedWatching:
|
|
1960
1973
|
type: integer
|
|
1961
|
-
description: Viewers who started watching in this segment
|
|
1974
|
+
description: 'Viewers who started watching in this segment. 0 when YouTube has no segment-level data for the video.'
|
|
1962
1975
|
stoppedWatching:
|
|
1963
1976
|
type: integer
|
|
1964
|
-
description: Viewers who stopped watching in this segment
|
|
1977
|
+
description: 'Viewers who stopped watching in this segment. 0 when YouTube has no segment-level data for the video.'
|
|
1965
1978
|
totalSegmentImpressions:
|
|
1966
1979
|
type: integer
|
|
1967
1980
|
description: Total views of this segment, including rewatches
|
|
@@ -2325,7 +2338,7 @@ components:
|
|
|
2325
2338
|
type: array
|
|
2326
2339
|
items:
|
|
2327
2340
|
type: string
|
|
2328
|
-
enum: [post.scheduled, post.published, post.failed, post.partial, post.cancelled, post.recycled, post.platform.published, post.platform.failed, post.platform.deleted, post.tiktok.url_resolved, post.external.created, post.external.updated, post.external.deleted, account.connected, account.disconnected, account.ads.initial_sync_completed, message.received, conversation.started, call.received, call.ended, call.failed, call.permission_request, message.sent, message.edited, message.deleted, message.delivered, message.read, message.failed, reaction.received, comment.received, review.new, review.updated, lead.received, ad.status_changed, whatsapp.template.status_updated, whatsapp.automatic_event, whatsapp.number.activated, whatsapp.number.declined, whatsapp.number.action_required, whatsapp.number.verification_required, whatsapp.number.suspended, whatsapp.number.reactivated, whatsapp.number.released, whatsapp.number.kyc_submitted, verification.approved, verification.failed]
|
|
2341
|
+
enum: [post.scheduled, post.published, post.failed, post.partial, post.cancelled, post.recycled, post.platform.published, post.platform.failed, post.platform.deleted, post.tiktok.url_resolved, post.external.created, post.external.updated, post.external.deleted, account.connected, account.disconnected, account.ads.initial_sync_completed, message.received, conversation.started, call.received, call.ended, call.failed, call.permission_request, message.sent, message.edited, message.deleted, message.delivered, message.read, message.failed, reaction.received, referral.received, comment.received, review.new, review.updated, lead.received, ad.status_changed, whatsapp.template.status_updated, whatsapp.template.category_updated, whatsapp.automatic_event, whatsapp.number.activated, whatsapp.number.declined, whatsapp.number.action_required, whatsapp.number.verification_required, whatsapp.number.suspended, whatsapp.number.reactivated, whatsapp.number.released, whatsapp.number.kyc_submitted, verification.approved, verification.failed]
|
|
2329
2342
|
description: Events subscribed to
|
|
2330
2343
|
isActive:
|
|
2331
2344
|
type: boolean
|
|
@@ -2462,6 +2475,7 @@ components:
|
|
|
2462
2475
|
timestamp:
|
|
2463
2476
|
type: string
|
|
2464
2477
|
format: date-time
|
|
2478
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
2465
2479
|
WebhookPayloadPostPlatform:
|
|
2466
2480
|
type: object
|
|
2467
2481
|
description: |
|
|
@@ -2554,6 +2568,7 @@ components:
|
|
|
2554
2568
|
timestamp:
|
|
2555
2569
|
type: string
|
|
2556
2570
|
format: date-time
|
|
2571
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
2557
2572
|
WebhookPayloadAccountConnected:
|
|
2558
2573
|
type: object
|
|
2559
2574
|
description: Webhook payload for account connected events
|
|
@@ -2584,6 +2599,7 @@ components:
|
|
|
2584
2599
|
timestamp:
|
|
2585
2600
|
type: string
|
|
2586
2601
|
format: date-time
|
|
2602
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
2587
2603
|
WebhookPayloadAccountDisconnected:
|
|
2588
2604
|
type: object
|
|
2589
2605
|
description: Webhook payload for account disconnected events
|
|
@@ -2621,6 +2637,7 @@ components:
|
|
|
2621
2637
|
timestamp:
|
|
2622
2638
|
type: string
|
|
2623
2639
|
format: date-time
|
|
2640
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
2624
2641
|
WebhookPayloadAccountAdsInitialSyncCompleted:
|
|
2625
2642
|
type: object
|
|
2626
2643
|
description: |
|
|
@@ -2723,6 +2740,7 @@ components:
|
|
|
2723
2740
|
timestamp:
|
|
2724
2741
|
type: string
|
|
2725
2742
|
format: date-time
|
|
2743
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
2726
2744
|
WebhookPayloadComment:
|
|
2727
2745
|
type: object
|
|
2728
2746
|
description: Webhook payload for comment received events (Instagram, Facebook, Twitter/X, YouTube, LinkedIn, Bluesky, Reddit)
|
|
@@ -2766,6 +2784,9 @@ components:
|
|
|
2766
2784
|
type: string
|
|
2767
2785
|
picture:
|
|
2768
2786
|
type: [string, "null"]
|
|
2787
|
+
isOwnAccount:
|
|
2788
|
+
type: boolean
|
|
2789
|
+
description: 'True when this comment was authored by the connected account itself (Meta re-delivers the account''s own replies as comments events). Populated on the Instagram and Facebook realtime webhooks only; absent means not evaluated, never "not the account".'
|
|
2769
2790
|
instagramProfile:
|
|
2770
2791
|
type: object
|
|
2771
2792
|
description: |
|
|
@@ -2867,6 +2888,7 @@ components:
|
|
|
2867
2888
|
timestamp:
|
|
2868
2889
|
type: string
|
|
2869
2890
|
format: date-time
|
|
2891
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
2870
2892
|
WebhookPayloadLead:
|
|
2871
2893
|
type: object
|
|
2872
2894
|
description: Webhook payload for lead.received events (Meta Lead Gen / Instant Forms).
|
|
@@ -2931,6 +2953,7 @@ components:
|
|
|
2931
2953
|
timestamp:
|
|
2932
2954
|
type: string
|
|
2933
2955
|
format: date-time
|
|
2956
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
2934
2957
|
ReviewWebhookReview:
|
|
2935
2958
|
type: object
|
|
2936
2959
|
description: Review data shared by review.new and review.updated payloads.
|
|
@@ -3007,6 +3030,7 @@ components:
|
|
|
3007
3030
|
timestamp:
|
|
3008
3031
|
type: string
|
|
3009
3032
|
format: date-time
|
|
3033
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
3010
3034
|
WebhookPayloadReviewUpdated:
|
|
3011
3035
|
type: object
|
|
3012
3036
|
description: |
|
|
@@ -3040,6 +3064,7 @@ components:
|
|
|
3040
3064
|
timestamp:
|
|
3041
3065
|
type: string
|
|
3042
3066
|
format: date-time
|
|
3067
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
3043
3068
|
ExternalPostWebhookPost:
|
|
3044
3069
|
type: object
|
|
3045
3070
|
description: Native (external) post data shared by all post.external.* payloads.
|
|
@@ -3114,6 +3139,7 @@ components:
|
|
|
3114
3139
|
timestamp:
|
|
3115
3140
|
type: string
|
|
3116
3141
|
format: date-time
|
|
3142
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
3117
3143
|
# ─── Shared sub-schemas for inbox lifecycle webhook payloads ────────────
|
|
3118
3144
|
# WebhookPayloadMessageEdited / Deleted / DeliveryStatus reference these
|
|
3119
3145
|
# as $refs. They were added as top-level named schemas (rather than nested
|
|
@@ -3133,7 +3159,7 @@ components:
|
|
|
3133
3159
|
description: Internal conversation ID
|
|
3134
3160
|
platform:
|
|
3135
3161
|
type: string
|
|
3136
|
-
enum: [instagram, facebook, telegram, whatsapp]
|
|
3162
|
+
enum: [instagram, facebook, telegram, whatsapp, sms]
|
|
3137
3163
|
platformMessageId:
|
|
3138
3164
|
type: string
|
|
3139
3165
|
description: Platform's message ID
|
|
@@ -3303,7 +3329,7 @@ components:
|
|
|
3303
3329
|
sender:
|
|
3304
3330
|
type: object
|
|
3305
3331
|
required: [id]
|
|
3306
|
-
description: 'Whoever added or removed the reaction. Usually the participant, but on Slack, Instagram and Facebook Messenger it is the business own platform id when the
|
|
3332
|
+
description: 'Whoever added or removed the reaction. Usually the participant, but on WhatsApp, Slack, Instagram and Facebook Messenger it is the business own platform id when the business reacted from the native app or via the reactions API: compare it with conversation.participantId.'
|
|
3307
3333
|
properties:
|
|
3308
3334
|
id:
|
|
3309
3335
|
type: string
|
|
@@ -3329,6 +3355,77 @@ components:
|
|
|
3329
3355
|
timestamp:
|
|
3330
3356
|
type: string
|
|
3331
3357
|
format: date-time
|
|
3358
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
3359
|
+
# ────────────────────────────────────────────────────────────────────────
|
|
3360
|
+
WebhookPayloadReferral:
|
|
3361
|
+
type: object
|
|
3362
|
+
description: 'Webhook payload for referral received events (Instagram, Facebook Messenger)'
|
|
3363
|
+
required: [id, event, referral, sender, conversation, account, timestamp]
|
|
3364
|
+
properties:
|
|
3365
|
+
id:
|
|
3366
|
+
type: string
|
|
3367
|
+
description: Stable webhook event ID
|
|
3368
|
+
event:
|
|
3369
|
+
type: string
|
|
3370
|
+
enum: [referral.received]
|
|
3371
|
+
referral:
|
|
3372
|
+
type: object
|
|
3373
|
+
description: |
|
|
3374
|
+
Meta's referral object, forwarded verbatim. Same shape as
|
|
3375
|
+
`metadata.referral` on `message.received`: `ref` + `source` for
|
|
3376
|
+
ig.me / m.me links, `ad_id` + `ads_context_data` for returning
|
|
3377
|
+
Messenger ad clicks.
|
|
3378
|
+
properties:
|
|
3379
|
+
ref:
|
|
3380
|
+
type: string
|
|
3381
|
+
description: The `ref` parameter of the clicked ig.me / m.me link or ad.
|
|
3382
|
+
source:
|
|
3383
|
+
type: string
|
|
3384
|
+
description: 'Meta-supplied source (`SHORTLINK`, `SHORTLINKS`, `IGME-SOURCE-LINK`, `ADS` - treat as opaque).'
|
|
3385
|
+
type:
|
|
3386
|
+
type: string
|
|
3387
|
+
description: Meta-supplied referral type (e.g. `OPEN_THREAD`).
|
|
3388
|
+
referer_uri:
|
|
3389
|
+
type: string
|
|
3390
|
+
description: URI of the originating site, when Meta supplies one. Facebook Messenger only.
|
|
3391
|
+
ad_id:
|
|
3392
|
+
type: string
|
|
3393
|
+
description: The Meta ad ID, on returning ad clicks. Facebook Messenger only.
|
|
3394
|
+
ads_context_data:
|
|
3395
|
+
type: object
|
|
3396
|
+
description: Snapshot of the ad's public context at click time.
|
|
3397
|
+
properties:
|
|
3398
|
+
ad_title:
|
|
3399
|
+
type: string
|
|
3400
|
+
photo_url:
|
|
3401
|
+
type: string
|
|
3402
|
+
video_url:
|
|
3403
|
+
type: string
|
|
3404
|
+
post_id:
|
|
3405
|
+
type: string
|
|
3406
|
+
product_id:
|
|
3407
|
+
type: string
|
|
3408
|
+
flow_id:
|
|
3409
|
+
type: string
|
|
3410
|
+
sender:
|
|
3411
|
+
type: object
|
|
3412
|
+
required: [id]
|
|
3413
|
+
description: Who clicked - the conversation participant.
|
|
3414
|
+
properties:
|
|
3415
|
+
id:
|
|
3416
|
+
type: string
|
|
3417
|
+
description: Platform-scoped user ID (IGSID / PSID).
|
|
3418
|
+
contactId:
|
|
3419
|
+
type: string
|
|
3420
|
+
description: Zernio CRM Contact id for this sender, when one exists.
|
|
3421
|
+
conversation:
|
|
3422
|
+
$ref: '#/components/schemas/InboxWebhookConversation'
|
|
3423
|
+
account:
|
|
3424
|
+
$ref: '#/components/schemas/InboxWebhookAccount'
|
|
3425
|
+
timestamp:
|
|
3426
|
+
type: string
|
|
3427
|
+
format: date-time
|
|
3428
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
3332
3429
|
# ────────────────────────────────────────────────────────────────────────
|
|
3333
3430
|
WebhookPayloadMessage:
|
|
3334
3431
|
type: object
|
|
@@ -3353,7 +3450,7 @@ components:
|
|
|
3353
3450
|
description: Internal conversation ID
|
|
3354
3451
|
platform:
|
|
3355
3452
|
type: string
|
|
3356
|
-
enum: [instagram, facebook, telegram, whatsapp]
|
|
3453
|
+
enum: [instagram, facebook, telegram, whatsapp, sms]
|
|
3357
3454
|
platformMessageId:
|
|
3358
3455
|
type: string
|
|
3359
3456
|
description: Platform's message ID
|
|
@@ -3606,17 +3703,27 @@ components:
|
|
|
3606
3703
|
referral:
|
|
3607
3704
|
type: [object, "null"]
|
|
3608
3705
|
description: |
|
|
3609
|
-
|
|
3706
|
+
Click attribution forwarded verbatim from Meta. Populated only on
|
|
3610
3707
|
the FIRST inbound message after the click; absent on subsequent
|
|
3611
|
-
messages of the same conversation.
|
|
3708
|
+
messages of the same conversation. On Instagram and Messenger a
|
|
3709
|
+
RETURNING click also attaches it to the first message that
|
|
3710
|
+
follows, so read it on every `message.received` for per-click
|
|
3711
|
+
attribution; a click that opens an existing thread WITHOUT a
|
|
3712
|
+
message arrives as the separate `referral.received` event.
|
|
3612
3713
|
|
|
3613
|
-
The populated subset identifies the source
|
|
3714
|
+
The populated subset identifies the source:
|
|
3614
3715
|
- `ctwa_clid` and `source_*` fields: WhatsApp CTWA
|
|
3615
3716
|
(Click-to-WhatsApp). Attribution window is 7 days from click.
|
|
3616
3717
|
Forward to Meta Conversions API for Business Messaging replay.
|
|
3617
3718
|
- `ad_id` and `ads_context_data`: Facebook Messenger CTM
|
|
3618
3719
|
(Click-to-Message) or Instagram CTD (Click-to-Direct). Use
|
|
3619
3720
|
`ad_id` to attribute the conversation to a specific ad.
|
|
3721
|
+
- `ref` without `ad_id`: an ig.me / m.me link carrying a
|
|
3722
|
+
`?ref=` parameter (`source` is `SHORTLINK`, `SHORTLINKS` or
|
|
3723
|
+
`IGME-SOURCE-LINK` depending on surface - treat it as
|
|
3724
|
+
opaque). Instagram delivers ig.me refs on new threads only
|
|
3725
|
+
when the account has at least one Ice Breaker configured
|
|
3726
|
+
(`PUT /v1/accounts/{accountId}/instagram-ice-breakers`).
|
|
3620
3727
|
properties:
|
|
3621
3728
|
ctwa_clid:
|
|
3622
3729
|
type: string
|
|
@@ -3647,18 +3754,25 @@ components:
|
|
|
3647
3754
|
ref:
|
|
3648
3755
|
type: string
|
|
3649
3756
|
description: |
|
|
3650
|
-
|
|
3651
|
-
|
|
3757
|
+
The `ref` parameter passed through from the Meta ad creative
|
|
3758
|
+
or from an ig.me / m.me link. Instagram / Facebook Messenger
|
|
3759
|
+
only.
|
|
3652
3760
|
source:
|
|
3653
3761
|
type: string
|
|
3654
3762
|
description: |
|
|
3655
|
-
Meta-supplied source identifier (
|
|
3656
|
-
|
|
3763
|
+
Meta-supplied source identifier (`ADS` for ad clicks;
|
|
3764
|
+
`SHORTLINK`, `SHORTLINKS` or `IGME-SOURCE-LINK` for ref
|
|
3765
|
+
links). Instagram / Facebook Messenger only.
|
|
3657
3766
|
type:
|
|
3658
3767
|
type: string
|
|
3659
3768
|
description: |
|
|
3660
|
-
Meta-supplied referral type (e.g. `OPEN_THREAD`).
|
|
3661
|
-
Messenger
|
|
3769
|
+
Meta-supplied referral type (e.g. `OPEN_THREAD`). Instagram /
|
|
3770
|
+
Facebook Messenger only.
|
|
3771
|
+
referer_uri:
|
|
3772
|
+
type: string
|
|
3773
|
+
description: |
|
|
3774
|
+
URI of the originating site, when Meta supplies one (m.me
|
|
3775
|
+
links opened from the web). Facebook Messenger only.
|
|
3662
3776
|
ads_context_data:
|
|
3663
3777
|
type: object
|
|
3664
3778
|
description: |
|
|
@@ -3677,9 +3791,39 @@ components:
|
|
|
3677
3791
|
type: string
|
|
3678
3792
|
flow_id:
|
|
3679
3793
|
type: string
|
|
3794
|
+
unsupported:
|
|
3795
|
+
type: object
|
|
3796
|
+
description: |
|
|
3797
|
+
WhatsApp only. Meta's own reason this message has no
|
|
3798
|
+
renderable body. Present when Meta attached an error to the
|
|
3799
|
+
inbound payload; in practice the `unsupported`, `errors` and
|
|
3800
|
+
`unknown` types (code 131051: message type currently not
|
|
3801
|
+
supported). `text` on those messages is the fixed
|
|
3802
|
+
`[Unsupported message]` placeholder.
|
|
3803
|
+
properties:
|
|
3804
|
+
code:
|
|
3805
|
+
type: integer
|
|
3806
|
+
description: Meta's numeric error code (e.g. 131051).
|
|
3807
|
+
title:
|
|
3808
|
+
type: string
|
|
3809
|
+
description: Meta's short error title.
|
|
3810
|
+
details:
|
|
3811
|
+
type: string
|
|
3812
|
+
description: Meta's human-readable error detail string.
|
|
3813
|
+
noRenderableContent:
|
|
3814
|
+
type: boolean
|
|
3815
|
+
description: |
|
|
3816
|
+
Instagram / Facebook Messenger only. Set when the message
|
|
3817
|
+
carries nothing an integrator can render (a `template`
|
|
3818
|
+
attachment with no text and no parseable content, or Meta's
|
|
3819
|
+
own `is_unsupported` flag). Sibling of `unsupported` above
|
|
3820
|
+
(WhatsApp only, carries Meta's error code/title/details): this
|
|
3821
|
+
field has no error envelope, just the boolean. Absence means
|
|
3822
|
+
"not flagged", never "checked and renderable".
|
|
3680
3823
|
timestamp:
|
|
3681
3824
|
type: string
|
|
3682
3825
|
format: date-time
|
|
3826
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
3683
3827
|
WebhookPayloadMessageSent:
|
|
3684
3828
|
type: object
|
|
3685
3829
|
description: Webhook payload for message sent events (fired when a message is sent via the API, or from the WhatsApp Business app on Coexistence numbers)
|
|
@@ -3765,6 +3909,7 @@ components:
|
|
|
3765
3909
|
timestamp:
|
|
3766
3910
|
type: string
|
|
3767
3911
|
format: date-time
|
|
3912
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
3768
3913
|
InboxMessageEditAttachment:
|
|
3769
3914
|
type: object
|
|
3770
3915
|
description: Attachment snapshot inside an edit-history entry.
|
|
@@ -3817,7 +3962,10 @@ components:
|
|
|
3817
3962
|
$ref: '#/components/schemas/InboxWebhookConversation'
|
|
3818
3963
|
account:
|
|
3819
3964
|
$ref: '#/components/schemas/InboxWebhookAccount'
|
|
3820
|
-
timestamp:
|
|
3965
|
+
timestamp:
|
|
3966
|
+
type: string
|
|
3967
|
+
format: date-time
|
|
3968
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
3821
3969
|
WebhookPayloadMessageDeleted:
|
|
3822
3970
|
type: object
|
|
3823
3971
|
description: |
|
|
@@ -3843,7 +3991,10 @@ components:
|
|
|
3843
3991
|
$ref: '#/components/schemas/InboxWebhookConversation'
|
|
3844
3992
|
account:
|
|
3845
3993
|
$ref: '#/components/schemas/InboxWebhookAccount'
|
|
3846
|
-
timestamp:
|
|
3994
|
+
timestamp:
|
|
3995
|
+
type: string
|
|
3996
|
+
format: date-time
|
|
3997
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
3847
3998
|
WebhookPayloadMessageDeliveryStatus:
|
|
3848
3999
|
type: object
|
|
3849
4000
|
description: |
|
|
@@ -3852,10 +4003,12 @@ components:
|
|
|
3852
4003
|
delivery state for an outgoing message.
|
|
3853
4004
|
|
|
3854
4005
|
Platform support:
|
|
3855
|
-
* message.delivered
|
|
3856
|
-
* message.read
|
|
3857
|
-
|
|
3858
|
-
|
|
4006
|
+
* message.delivered: WhatsApp, Facebook Messenger, SMS.
|
|
4007
|
+
* message.read: WhatsApp, Facebook Messenger, Instagram. Not SMS
|
|
4008
|
+
(carriers report delivery, never read).
|
|
4009
|
+
* message.failed: WhatsApp and SMS (other platforms don't expose
|
|
4010
|
+
per-message failure via webhook). On SMS, `error.code` is the
|
|
4011
|
+
carrier's numeric code and `error.message` its reason.
|
|
3859
4012
|
required: [id, event, message, statusAt, conversation, account, timestamp]
|
|
3860
4013
|
properties:
|
|
3861
4014
|
id: { type: string }
|
|
@@ -3886,7 +4039,10 @@ components:
|
|
|
3886
4039
|
$ref: '#/components/schemas/InboxWebhookConversation'
|
|
3887
4040
|
account:
|
|
3888
4041
|
$ref: '#/components/schemas/InboxWebhookAccount'
|
|
3889
|
-
timestamp:
|
|
4042
|
+
timestamp:
|
|
4043
|
+
type: string
|
|
4044
|
+
format: date-time
|
|
4045
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
3890
4046
|
WebhookPayloadConversationStarted:
|
|
3891
4047
|
type: object
|
|
3892
4048
|
description: |
|
|
@@ -3931,7 +4087,10 @@ components:
|
|
|
3931
4087
|
type: string
|
|
3932
4088
|
format: date-time
|
|
3933
4089
|
description: When the conversation document was created.
|
|
3934
|
-
timestamp:
|
|
4090
|
+
timestamp:
|
|
4091
|
+
type: string
|
|
4092
|
+
format: date-time
|
|
4093
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
3935
4094
|
CallRecord:
|
|
3936
4095
|
type: object
|
|
3937
4096
|
description: |
|
|
@@ -4027,7 +4186,10 @@ components:
|
|
|
4027
4186
|
conversationId: { type: string }
|
|
4028
4187
|
startedAt: { type: string, format: date-time }
|
|
4029
4188
|
account: { $ref: '#/components/schemas/InboxWebhookAccount' }
|
|
4030
|
-
timestamp:
|
|
4189
|
+
timestamp:
|
|
4190
|
+
type: string
|
|
4191
|
+
format: date-time
|
|
4192
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
4031
4193
|
WebhookPayloadCallEnded:
|
|
4032
4194
|
type: object
|
|
4033
4195
|
description: |
|
|
@@ -4053,6 +4215,8 @@ components:
|
|
|
4053
4215
|
endedAt: { type: string, format: date-time }
|
|
4054
4216
|
durationSeconds: { type: integer }
|
|
4055
4217
|
endReason: { type: string, enum: [hangup, no_answer, rejected, error] }
|
|
4218
|
+
hangupCause: { type: [string, "null"], description: "Raw carrier hangup cause behind endReason (e.g. normal_clearing, call_rejected, not_found). Null when the carrier reported none." }
|
|
4219
|
+
sipHangupCause: { type: [string, "null"], description: "SIP response code that ended the call when SIP-signalled (e.g. '403', '486', '603'). endReason collapses all three to 'rejected', so this is what separates a refused destination from a busy line. Null on non-SIP legs." }
|
|
4056
4220
|
recordingUrl: { type: string }
|
|
4057
4221
|
recordingExpiresAt: { type: string, format: date-time }
|
|
4058
4222
|
billing:
|
|
@@ -4064,7 +4228,10 @@ components:
|
|
|
4064
4228
|
billableCostUSD: { type: number, description: 'The amount Zernio bills you = Telnyx leg + recording. Excludes Meta (billed by Meta directly).' }
|
|
4065
4229
|
totalCostUSD: { type: number, description: 'Full economic cost incl. the Meta portion you pay directly (Meta + Telnyx + recording). Display only, not the Zernio-billed amount.' }
|
|
4066
4230
|
account: { $ref: '#/components/schemas/InboxWebhookAccount' }
|
|
4067
|
-
timestamp:
|
|
4231
|
+
timestamp:
|
|
4232
|
+
type: string
|
|
4233
|
+
format: date-time
|
|
4234
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
4068
4235
|
WebhookPayloadCallFailed:
|
|
4069
4236
|
type: object
|
|
4070
4237
|
description: |
|
|
@@ -4093,7 +4260,10 @@ components:
|
|
|
4093
4260
|
code: { type: integer }
|
|
4094
4261
|
message: { type: string }
|
|
4095
4262
|
account: { $ref: '#/components/schemas/InboxWebhookAccount' }
|
|
4096
|
-
timestamp:
|
|
4263
|
+
timestamp:
|
|
4264
|
+
type: string
|
|
4265
|
+
format: date-time
|
|
4266
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
4097
4267
|
WebhookPayloadCallPermissionRequest:
|
|
4098
4268
|
type: object
|
|
4099
4269
|
description: |
|
|
@@ -4115,7 +4285,10 @@ components:
|
|
|
4115
4285
|
expirationTimestamp: { type: string, format: date-time, description: "Present only when temporary" }
|
|
4116
4286
|
responseSource: { type: string, description: "Meta's response source, typically `user_action`" }
|
|
4117
4287
|
account: { $ref: '#/components/schemas/InboxWebhookAccount' }
|
|
4118
|
-
timestamp:
|
|
4288
|
+
timestamp:
|
|
4289
|
+
type: string
|
|
4290
|
+
format: date-time
|
|
4291
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
4119
4292
|
WebhookPayloadAdStatusChanged:
|
|
4120
4293
|
type: object
|
|
4121
4294
|
description: |
|
|
@@ -4224,7 +4397,7 @@ components:
|
|
|
4224
4397
|
timestamp:
|
|
4225
4398
|
type: string
|
|
4226
4399
|
format: date-time
|
|
4227
|
-
description:
|
|
4400
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
4228
4401
|
WebhookPayloadWhatsAppTemplateStatusUpdated:
|
|
4229
4402
|
type: object
|
|
4230
4403
|
description: |
|
|
@@ -4277,7 +4450,70 @@ components:
|
|
|
4277
4450
|
timestamp:
|
|
4278
4451
|
type: string
|
|
4279
4452
|
format: date-time
|
|
4280
|
-
description:
|
|
4453
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
4454
|
+
WebhookPayloadWhatsAppTemplateCategoryUpdated:
|
|
4455
|
+
type: object
|
|
4456
|
+
description: |
|
|
4457
|
+
Webhook payload for the `whatsapp.template.category_updated` event.
|
|
4458
|
+
Fired when Meta reclassifies a template's category attached to a
|
|
4459
|
+
connected WABA. Maps Meta's `template_category_update` field onto
|
|
4460
|
+
our event envelope.
|
|
4461
|
+
required: [id, event, account, template, timestamp]
|
|
4462
|
+
properties:
|
|
4463
|
+
id:
|
|
4464
|
+
type: string
|
|
4465
|
+
description: Stable webhook event ID
|
|
4466
|
+
event:
|
|
4467
|
+
type: string
|
|
4468
|
+
enum: [whatsapp.template.category_updated]
|
|
4469
|
+
account:
|
|
4470
|
+
type: object
|
|
4471
|
+
required: [accountId, profileId, platform, username]
|
|
4472
|
+
properties:
|
|
4473
|
+
accountId: { type: string }
|
|
4474
|
+
profileId: { type: string }
|
|
4475
|
+
platform: { type: string, enum: [whatsapp] }
|
|
4476
|
+
username: { type: string }
|
|
4477
|
+
displayName: { type: string }
|
|
4478
|
+
template:
|
|
4479
|
+
type: object
|
|
4480
|
+
required: [templateId, name, language, changeType, category]
|
|
4481
|
+
properties:
|
|
4482
|
+
templateId:
|
|
4483
|
+
type: string
|
|
4484
|
+
description: Meta's `message_template_id`, returned as a string.
|
|
4485
|
+
name:
|
|
4486
|
+
type: string
|
|
4487
|
+
description: Meta's `message_template_name`.
|
|
4488
|
+
language:
|
|
4489
|
+
type: string
|
|
4490
|
+
description: Meta's `message_template_language` (e.g. `en_US`).
|
|
4491
|
+
changeType:
|
|
4492
|
+
type: string
|
|
4493
|
+
enum: [scheduled, applied]
|
|
4494
|
+
description: |
|
|
4495
|
+
`scheduled` is Meta's 24h advance notice of an upcoming
|
|
4496
|
+
reclassification; `applied` is the change taking effect.
|
|
4497
|
+
category:
|
|
4498
|
+
type: string
|
|
4499
|
+
enum: [UTILITY, MARKETING, AUTHENTICATION]
|
|
4500
|
+
description: The category right now, regardless of changeType.
|
|
4501
|
+
previousCategory:
|
|
4502
|
+
type: string
|
|
4503
|
+
enum: [UTILITY, MARKETING, AUTHENTICATION]
|
|
4504
|
+
description: Present only when changeType is `applied`. The category before this change.
|
|
4505
|
+
scheduledCategory:
|
|
4506
|
+
type: string
|
|
4507
|
+
enum: [UTILITY, MARKETING, AUTHENTICATION]
|
|
4508
|
+
description: Present only when changeType is `scheduled`. The category that will take effect at `effectiveAt`.
|
|
4509
|
+
effectiveAt:
|
|
4510
|
+
type: string
|
|
4511
|
+
format: date-time
|
|
4512
|
+
description: Present only when changeType is `scheduled`. ISO-8601 timestamp when the scheduled category takes effect.
|
|
4513
|
+
timestamp:
|
|
4514
|
+
type: string
|
|
4515
|
+
format: date-time
|
|
4516
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
4281
4517
|
WebhookPayloadTest:
|
|
4282
4518
|
type: object
|
|
4283
4519
|
description: Webhook payload for test deliveries
|
|
@@ -4295,6 +4531,7 @@ components:
|
|
|
4295
4531
|
timestamp:
|
|
4296
4532
|
type: string
|
|
4297
4533
|
format: date-time
|
|
4534
|
+
description: 'UTC time at which Zernio generated this test event (set once when the payload is built). Test fires are sent synchronously as a single attempt; a later redelivery of this event keeps the original value.'
|
|
4298
4535
|
DiscordGuildMember:
|
|
4299
4536
|
type: object
|
|
4300
4537
|
description: A Discord guild member, returned verbatim from Discord's API.
|
|
@@ -4387,18 +4624,34 @@ components:
|
|
|
4387
4624
|
description: >
|
|
4388
4625
|
A media item on a native (external/synced) post, as carried by post.external.*
|
|
4389
4626
|
webhook payloads. Distinct from the richer MediaItem used for Zernio-authored
|
|
4390
|
-
posts: external items are always already-published
|
|
4391
|
-
|
|
4392
|
-
|
|
4627
|
+
posts: external items are always already-published and limited to image or
|
|
4628
|
+
video. Kept as a separate schema so the generated SDK model does not collide
|
|
4629
|
+
with MediaItem.
|
|
4393
4630
|
required: [type, url]
|
|
4394
4631
|
properties:
|
|
4395
4632
|
type:
|
|
4396
4633
|
type: string
|
|
4397
4634
|
enum: [image, video]
|
|
4398
4635
|
url:
|
|
4399
|
-
type: string
|
|
4636
|
+
type: [string, "null"]
|
|
4637
|
+
description: >-
|
|
4638
|
+
'Direct URL to the media file. Null when the platform withholds it: check
|
|
4639
|
+
mediaStatus before downloading. Instagram omits the video file for Reels it
|
|
4640
|
+
flags as containing copyrighted material (its docs name audio as the usual
|
|
4641
|
+
cause), so type stays "video" while the file is permanently unreachable.
|
|
4642
|
+
For LinkedIn videos where the platform returns no file, url falls back to
|
|
4643
|
+
the cover image and the item carries mediaStatus: unavailable.'
|
|
4400
4644
|
thumbnail:
|
|
4401
4645
|
type: string
|
|
4646
|
+
description: 'Cover image. Still present when url is null.'
|
|
4647
|
+
mediaStatus:
|
|
4648
|
+
type: string
|
|
4649
|
+
enum: [available, unavailable]
|
|
4650
|
+
description: 'unavailable means the media file could not be retrieved (url is null or, for LinkedIn videos, a cover image standing in for the file). available or absent means the file is available at url (older synced items omit the field).'
|
|
4651
|
+
unavailableReason:
|
|
4652
|
+
type: string
|
|
4653
|
+
enum: [platform_withheld]
|
|
4654
|
+
description: 'Why the file is missing. platform_withheld means the platform declined to return it and retrying will not help.'
|
|
4402
4655
|
PlatformTarget:
|
|
4403
4656
|
type: object
|
|
4404
4657
|
properties:
|
|
@@ -4449,9 +4702,8 @@ components:
|
|
|
4449
4702
|
description: The native post ID on the platform (populated after successful publish)
|
|
4450
4703
|
example: "1234567890123456789"
|
|
4451
4704
|
platformPostUrl:
|
|
4452
|
-
type: string
|
|
4453
|
-
|
|
4454
|
-
description: Public URL of the published post. Included in the response for immediate posts; for scheduled posts, fetch via GET /v1/posts/{postId} after publish time.
|
|
4705
|
+
type: [string, "null"]
|
|
4706
|
+
description: Public URL of the published post. Included in the response for immediate posts; for scheduled posts, fetch via GET /v1/posts/{postId} after publish time. Empty when the platform confirmed the publish without returning an id a permalink can be built from (TikTok returns a publish id for some uploads); the TikTok reconcile cron backfills it later.
|
|
4455
4707
|
example: "https://twitter.com/acmecorp/status/1234567890123456789"
|
|
4456
4708
|
publishedAt:
|
|
4457
4709
|
type: string
|
|
@@ -4488,8 +4740,8 @@ components:
|
|
|
4488
4740
|
description: Human-readable error message when status is failed. Contains platform-specific error details explaining why the publish failed.
|
|
4489
4741
|
errorCategory:
|
|
4490
4742
|
type: string
|
|
4491
|
-
enum: [auth_expired, user_content, user_abuse, account_issue, platform_rejected, platform_error, system_error, unknown]
|
|
4492
|
-
description: "Error category for programmatic handling: auth_expired (token expired/revoked), user_content (wrong format/too long), user_abuse (rate limits/spam), account_issue (config problems), platform_rejected (policy violation), platform_error (5xx/maintenance), system_error (Zernio infra), unknown"
|
|
4743
|
+
enum: [auth_expired, user_content, user_abuse, account_issue, platform_rejected, platform_error, platform_rate_limit, quota_exhausted, system_error, unknown]
|
|
4744
|
+
description: "Error category for programmatic handling: auth_expired (token expired/revoked), user_content (wrong format/too long), user_abuse (rate limits/spam), account_issue (config problems), platform_rejected (policy violation), platform_error (5xx/maintenance), platform_rate_limit (platform throttling, retried automatically), quota_exhausted (shared daily API quota empty, resumes at the platform's reset), system_error (Zernio infra), unknown"
|
|
4493
4745
|
errorSource:
|
|
4494
4746
|
type: string
|
|
4495
4747
|
enum: [user, platform, system]
|
|
@@ -4631,9 +4883,239 @@ components:
|
|
|
4631
4883
|
format: date-time
|
|
4632
4884
|
description: When the last recycled copy was created (read-only)
|
|
4633
4885
|
|
|
4886
|
+
XArticleTextRange:
|
|
4887
|
+
type: object
|
|
4888
|
+
additionalProperties: false
|
|
4889
|
+
required: [from_index, to_index, text]
|
|
4890
|
+
properties:
|
|
4891
|
+
from_index:
|
|
4892
|
+
type: integer
|
|
4893
|
+
minimum: 0
|
|
4894
|
+
description: Inclusive start index in the block text.
|
|
4895
|
+
to_index:
|
|
4896
|
+
type: integer
|
|
4897
|
+
minimum: 0
|
|
4898
|
+
description: Exclusive end index in the block text. Must be greater than or equal to from_index and no greater than the block text length.
|
|
4899
|
+
text: { type: string, description: Text represented by this metadata range. }
|
|
4900
|
+
|
|
4901
|
+
XArticleInlineStyleRange:
|
|
4902
|
+
type: object
|
|
4903
|
+
additionalProperties: false
|
|
4904
|
+
required: [offset, length, style]
|
|
4905
|
+
properties:
|
|
4906
|
+
offset: { type: integer, minimum: 0 }
|
|
4907
|
+
length: { type: integer, minimum: 0 }
|
|
4908
|
+
style: { type: string, enum: [bold, italic, strikethrough] }
|
|
4909
|
+
description: The offset plus length must not exceed the containing block's text length.
|
|
4910
|
+
|
|
4911
|
+
XArticleEntityRange:
|
|
4912
|
+
type: object
|
|
4913
|
+
additionalProperties: false
|
|
4914
|
+
required: [key, offset, length]
|
|
4915
|
+
properties:
|
|
4916
|
+
key:
|
|
4917
|
+
type: integer
|
|
4918
|
+
minimum: 0
|
|
4919
|
+
description: Zero-based index into content_state.entities.
|
|
4920
|
+
offset: { type: integer, minimum: 0 }
|
|
4921
|
+
length: { type: integer, minimum: 0 }
|
|
4922
|
+
description: The referenced entity must exist, and offset plus length must not exceed the containing block's text length.
|
|
4923
|
+
|
|
4924
|
+
XArticleBlock:
|
|
4925
|
+
type: object
|
|
4926
|
+
additionalProperties: false
|
|
4927
|
+
required: [type, text]
|
|
4928
|
+
properties:
|
|
4929
|
+
type:
|
|
4930
|
+
type: string
|
|
4931
|
+
enum: [unstyled, header-one, header-two, header-three, unordered-list-item, ordered-list-item, blockquote, atomic]
|
|
4932
|
+
text: { type: string }
|
|
4933
|
+
key: { type: string, minLength: 1 }
|
|
4934
|
+
data:
|
|
4935
|
+
type: object
|
|
4936
|
+
additionalProperties: false
|
|
4937
|
+
properties:
|
|
4938
|
+
cashtags: { type: array, items: { $ref: '#/components/schemas/XArticleTextRange' } }
|
|
4939
|
+
hashtags: { type: array, items: { $ref: '#/components/schemas/XArticleTextRange' } }
|
|
4940
|
+
mentions: { type: array, items: { $ref: '#/components/schemas/XArticleTextRange' } }
|
|
4941
|
+
urls: { type: array, items: { $ref: '#/components/schemas/XArticleTextRange' } }
|
|
4942
|
+
inline_style_ranges:
|
|
4943
|
+
type: array
|
|
4944
|
+
items: { $ref: '#/components/schemas/XArticleInlineStyleRange' }
|
|
4945
|
+
entity_ranges:
|
|
4946
|
+
type: array
|
|
4947
|
+
items: { $ref: '#/components/schemas/XArticleEntityRange' }
|
|
4948
|
+
|
|
4949
|
+
XArticleEntity:
|
|
4950
|
+
oneOf:
|
|
4951
|
+
- type: object
|
|
4952
|
+
additionalProperties: false
|
|
4953
|
+
required: [key, value]
|
|
4954
|
+
properties:
|
|
4955
|
+
key: { type: string, minLength: 1 }
|
|
4956
|
+
value:
|
|
4957
|
+
type: object
|
|
4958
|
+
additionalProperties: false
|
|
4959
|
+
required: [type, mutability, data]
|
|
4960
|
+
properties:
|
|
4961
|
+
type: { type: string, const: post }
|
|
4962
|
+
mutability: { type: string, enum: [immutable, mutable, segmented] }
|
|
4963
|
+
data:
|
|
4964
|
+
type: object
|
|
4965
|
+
additionalProperties: false
|
|
4966
|
+
required: [post_id]
|
|
4967
|
+
properties:
|
|
4968
|
+
post_id: { type: string, minLength: 1 }
|
|
4969
|
+
- type: object
|
|
4970
|
+
additionalProperties: false
|
|
4971
|
+
required: [key, value]
|
|
4972
|
+
properties:
|
|
4973
|
+
key: { type: string, minLength: 1 }
|
|
4974
|
+
value:
|
|
4975
|
+
type: object
|
|
4976
|
+
additionalProperties: false
|
|
4977
|
+
required: [type, mutability, data]
|
|
4978
|
+
properties:
|
|
4979
|
+
type: { type: string, const: link }
|
|
4980
|
+
mutability: { type: string, enum: [immutable, mutable, segmented] }
|
|
4981
|
+
data:
|
|
4982
|
+
type: object
|
|
4983
|
+
additionalProperties: false
|
|
4984
|
+
required: [url]
|
|
4985
|
+
properties:
|
|
4986
|
+
url: { type: string, format: uri }
|
|
4987
|
+
- type: object
|
|
4988
|
+
additionalProperties: false
|
|
4989
|
+
required: [key, value]
|
|
4990
|
+
properties:
|
|
4991
|
+
key: { type: string, minLength: 1 }
|
|
4992
|
+
value:
|
|
4993
|
+
type: object
|
|
4994
|
+
additionalProperties: false
|
|
4995
|
+
required: [type, mutability, data]
|
|
4996
|
+
properties:
|
|
4997
|
+
type: { type: string, const: image }
|
|
4998
|
+
mutability: { type: string, enum: [immutable, mutable, segmented] }
|
|
4999
|
+
data:
|
|
5000
|
+
type: object
|
|
5001
|
+
additionalProperties: false
|
|
5002
|
+
required: [url]
|
|
5003
|
+
properties:
|
|
5004
|
+
url:
|
|
5005
|
+
type: string
|
|
5006
|
+
format: uri
|
|
5007
|
+
pattern: '^https?://.+\.(?:[jJ][pP][eE]?[gG]|[pP][nN][gG]|[wW][eE][bB][pP]|[gG][iI][fF]|[mM][pP]4)(?:[?#].*)?$'
|
|
5008
|
+
description: Public image, GIF, or MP4 URL. Zernio uploads it to X and replaces it with native media metadata. Caller-supplied media IDs are rejected.
|
|
5009
|
+
caption: { type: string }
|
|
5010
|
+
altText:
|
|
5011
|
+
type: string
|
|
5012
|
+
maxLength: 1000
|
|
5013
|
+
description: Supported for image and GIF URLs; rejected for MP4 media.
|
|
5014
|
+
- type: object
|
|
5015
|
+
additionalProperties: false
|
|
5016
|
+
required: [key, value]
|
|
5017
|
+
properties:
|
|
5018
|
+
key: { type: string, minLength: 1 }
|
|
5019
|
+
value:
|
|
5020
|
+
type: object
|
|
5021
|
+
additionalProperties: false
|
|
5022
|
+
required: [type, mutability, data]
|
|
5023
|
+
properties:
|
|
5024
|
+
type: { type: string, const: emoji }
|
|
5025
|
+
mutability: { type: string, enum: [immutable, mutable, segmented] }
|
|
5026
|
+
data:
|
|
5027
|
+
type: object
|
|
5028
|
+
additionalProperties: false
|
|
5029
|
+
required: [entity_key]
|
|
5030
|
+
properties:
|
|
5031
|
+
entity_key: { type: string, minLength: 1 }
|
|
5032
|
+
- type: object
|
|
5033
|
+
additionalProperties: false
|
|
5034
|
+
required: [key, value]
|
|
5035
|
+
properties:
|
|
5036
|
+
key: { type: string, minLength: 1 }
|
|
5037
|
+
value:
|
|
5038
|
+
type: object
|
|
5039
|
+
additionalProperties: false
|
|
5040
|
+
required: [type, mutability, data]
|
|
5041
|
+
properties:
|
|
5042
|
+
type: { type: string, const: markdown }
|
|
5043
|
+
mutability: { type: string, enum: [immutable, mutable, segmented] }
|
|
5044
|
+
data:
|
|
5045
|
+
type: object
|
|
5046
|
+
additionalProperties: false
|
|
5047
|
+
required: [markdown]
|
|
5048
|
+
properties:
|
|
5049
|
+
markdown: { type: string }
|
|
5050
|
+
- type: object
|
|
5051
|
+
additionalProperties: false
|
|
5052
|
+
required: [key, value]
|
|
5053
|
+
properties:
|
|
5054
|
+
key: { type: string, minLength: 1 }
|
|
5055
|
+
value:
|
|
5056
|
+
type: object
|
|
5057
|
+
additionalProperties: false
|
|
5058
|
+
required: [type, mutability, data]
|
|
5059
|
+
properties:
|
|
5060
|
+
type: { type: string, enum: [divider, latex] }
|
|
5061
|
+
mutability: { type: string, enum: [immutable, mutable, segmented] }
|
|
5062
|
+
data: { type: object, additionalProperties: false }
|
|
5063
|
+
description: Entity keys must be unique decimal strings matching their zero-based array index (`"0"`, `"1"`, ...).
|
|
5064
|
+
|
|
5065
|
+
XArticleContentState:
|
|
5066
|
+
type: object
|
|
5067
|
+
additionalProperties: false
|
|
5068
|
+
externalDocs:
|
|
5069
|
+
description: Official X Article content format reference
|
|
5070
|
+
url: https://docs.x.com/x-api/articles/create-draft-article
|
|
5071
|
+
required: [blocks, entities]
|
|
5072
|
+
properties:
|
|
5073
|
+
blocks:
|
|
5074
|
+
type: array
|
|
5075
|
+
minItems: 1
|
|
5076
|
+
items: { $ref: '#/components/schemas/XArticleBlock' }
|
|
5077
|
+
entities:
|
|
5078
|
+
type: array
|
|
5079
|
+
items: { $ref: '#/components/schemas/XArticleEntity' }
|
|
5080
|
+
description: X's snake_case content-state shape. Standard DraftJS camelCase fields such as entityMap, inlineStyleRanges, and entityRanges are rejected.
|
|
5081
|
+
|
|
5082
|
+
XArticle:
|
|
5083
|
+
type: object
|
|
5084
|
+
additionalProperties: false
|
|
5085
|
+
required: [title, content_state]
|
|
5086
|
+
properties:
|
|
5087
|
+
title: { type: string, minLength: 1 }
|
|
5088
|
+
content_state: { $ref: '#/components/schemas/XArticleContentState' }
|
|
5089
|
+
mode:
|
|
5090
|
+
type: string
|
|
5091
|
+
enum: [publish, draft]
|
|
5092
|
+
default: publish
|
|
5093
|
+
description: Publish creates an X Article draft and then publishes it. Draft stops after draft creation and returns the X draft ID without a public URL.
|
|
5094
|
+
cover:
|
|
5095
|
+
type: object
|
|
5096
|
+
additionalProperties: false
|
|
5097
|
+
required: [url]
|
|
5098
|
+
properties:
|
|
5099
|
+
url:
|
|
5100
|
+
type: string
|
|
5101
|
+
format: uri
|
|
5102
|
+
pattern: '^https?://.+\.(?:[jJ][pP][eE]?[gG]|[pP][nN][gG]|[wW][eE][bB][pP])(?:[?#].*)?$'
|
|
5103
|
+
description: Public JPG, JPEG, PNG, or WebP URL. GIF, MP4, AVIF, extensionless URLs, and caller-supplied native media IDs are rejected.
|
|
5104
|
+
altText: { type: string, maxLength: 1000 }
|
|
5105
|
+
description: |
|
|
5106
|
+
Long-form X Article payload. X Articles require an eligible X Premium+ account.
|
|
5107
|
+
Articles are mutually exclusive with top-level/custom tweet media and with threadItems,
|
|
5108
|
+
poll, quoteTweetId, replyToTweetId, inReplyToTweetId, replySettings, sensitiveMedia,
|
|
5109
|
+
paidPartnership, and madeWithAi. Publishing normally performs two billable X API
|
|
5110
|
+
requests at $0.010 each (draft + publish, $0.020 total); mode `draft` performs only
|
|
5111
|
+
the $0.010 draft request. `articleDraftId` is an internal recovery checkpoint and
|
|
5112
|
+
must not be supplied by API clients.
|
|
5113
|
+
|
|
4634
5114
|
TwitterPlatformData:
|
|
4635
5115
|
type: object
|
|
4636
5116
|
properties:
|
|
5117
|
+
article:
|
|
5118
|
+
$ref: '#/components/schemas/XArticle'
|
|
4637
5119
|
replyToTweetId:
|
|
4638
5120
|
type: string
|
|
4639
5121
|
description: ID of an existing tweet to reply to. The published tweet will appear as a reply in that tweet's thread. For threads, only the first tweet replies to the target; subsequent tweets chain normally. X only permits replying to your own posts or posts you are mentioned in; replying to an arbitrary other account's post is rejected by X.
|
|
@@ -4707,9 +5189,9 @@ components:
|
|
|
4707
5189
|
type: boolean
|
|
4708
5190
|
description: Content has other sensitive characteristics.
|
|
4709
5191
|
description: >
|
|
4710
|
-
X
|
|
4711
|
-
|
|
4712
|
-
|
|
5192
|
+
X-specific post options. The article field creates a long-form X Article and is mutually
|
|
5193
|
+
exclusive with tweet media and tweet-only options. Geo-restriction applies at the media
|
|
5194
|
+
level: media is hidden outside the specified countries while tweet text remains visible.
|
|
4713
5195
|
|
|
4714
5196
|
ThreadsPlatformData:
|
|
4715
5197
|
type: object
|
|
@@ -4775,7 +5257,7 @@ components:
|
|
|
4775
5257
|
carouselCards:
|
|
4776
5258
|
type: array
|
|
4777
5259
|
minItems: 2
|
|
4778
|
-
maxItems:
|
|
5260
|
+
maxItems: 10
|
|
4779
5261
|
description: >
|
|
4780
5262
|
Renders the post as a multi-link carousel (organic Page post). When set, mediaItems
|
|
4781
5263
|
must be provided with the same length and all items must be images (no videos).
|
|
@@ -4955,13 +5437,41 @@ components:
|
|
|
4955
5437
|
description: Set to true to disable automatic link previews for URLs in the post content (default is false)
|
|
4956
5438
|
reshareUrl:
|
|
4957
5439
|
type: string
|
|
4958
|
-
description: "LinkedIn post link to repost (use the post's \"Copy link to post\" action), or a urn:li:share / urn:li:ugcPost / urn:li:groupPost URN.
|
|
5440
|
+
description: "LinkedIn post link to repost (use the post's \"Copy link to post\" action), or a urn:li:share / urn:li:ugcPost / urn:li:groupPost URN. With content, the published post is a quote-reshare: your text is the commentary and the original is embedded underneath (LinkedIn's \"repost with your thoughts\"). Leave content empty (and omit customContent) to publish a plain repost with no text, LinkedIn's one-click \"Repost\". Mutually exclusive with media. Works on personal profiles and organization pages."
|
|
4959
5441
|
geoRestriction:
|
|
4960
5442
|
$ref: '#/components/schemas/GeoRestriction'
|
|
5443
|
+
poll:
|
|
5444
|
+
type: object
|
|
5445
|
+
description: 'Create a LinkedIn poll with this post. Cannot be combined with media or reshareUrl. Polls cannot be edited after publishing on LinkedIn, and API-created polls are non-sponsored only (they cannot be promoted as ads).'
|
|
5446
|
+
properties:
|
|
5447
|
+
question:
|
|
5448
|
+
type: string
|
|
5449
|
+
minLength: 1
|
|
5450
|
+
maxLength: 140
|
|
5451
|
+
description: 'Poll question (max 140 characters)'
|
|
5452
|
+
options:
|
|
5453
|
+
type: array
|
|
5454
|
+
minItems: 2
|
|
5455
|
+
maxItems: 4
|
|
5456
|
+
items:
|
|
5457
|
+
type: string
|
|
5458
|
+
minLength: 1
|
|
5459
|
+
maxLength: 30
|
|
5460
|
+
description: 'Poll options (2-4 choices, max 30 characters each)'
|
|
5461
|
+
duration:
|
|
5462
|
+
type: string
|
|
5463
|
+
enum: [ONE_DAY, THREE_DAYS, SEVEN_DAYS, FOURTEEN_DAYS]
|
|
5464
|
+
default: SEVEN_DAYS
|
|
5465
|
+
description: How long the poll accepts votes. Defaults to SEVEN_DAYS.
|
|
5466
|
+
required:
|
|
5467
|
+
- question
|
|
5468
|
+
- options
|
|
4961
5469
|
description: >
|
|
4962
5470
|
Up to 20 images, no multi-video. Single PDF supported (max 100MB). Link previews auto-generated
|
|
4963
5471
|
when no media attached. Use organizationUrn for multi-org posting. Geo-restriction only works for
|
|
4964
5472
|
organization pages (not personal profiles) and requires the targeted audience to exceed 300 followers.
|
|
5473
|
+
Polls are supported via the poll object: 2-4 options, cannot be combined with media or reshareUrl,
|
|
5474
|
+
cannot be edited after publishing, and API-created polls are non-sponsored only.
|
|
4965
5475
|
|
|
4966
5476
|
MoneyAmount:
|
|
4967
5477
|
type: object
|
|
@@ -5649,6 +6159,21 @@ components:
|
|
|
5649
6159
|
BlueskyPlatformData:
|
|
5650
6160
|
type: object
|
|
5651
6161
|
properties:
|
|
6162
|
+
langs:
|
|
6163
|
+
type: array
|
|
6164
|
+
minItems: 1
|
|
6165
|
+
maxItems: 3
|
|
6166
|
+
items:
|
|
6167
|
+
type: string
|
|
6168
|
+
example: ["pt", "en"]
|
|
6169
|
+
description: >
|
|
6170
|
+
Language(s) of the post text as 1-3 BCP-47 codes (e.g. "pt", "en-US"), written to the
|
|
6171
|
+
post record's langs field. Bluesky feed generators filter on this field, so posts
|
|
6172
|
+
without it never appear in language-scoped feeds. Can only be set at creation
|
|
6173
|
+
(Bluesky has no post editing). When threadItems is used, every item in the thread
|
|
6174
|
+
carries the same langs. When omitted, the account's default (set via
|
|
6175
|
+
PATCH /v1/accounts/{accountId}/bluesky-settings) applies; with no default either,
|
|
6176
|
+
the field is absent from the record.
|
|
5652
6177
|
threadItems:
|
|
5653
6178
|
type: array
|
|
5654
6179
|
description: >
|
|
@@ -5666,7 +6191,7 @@ components:
|
|
|
5666
6191
|
items:
|
|
5667
6192
|
$ref: '#/components/schemas/MediaItem'
|
|
5668
6193
|
description: |
|
|
5669
|
-
Bluesky post settings. Supports text posts with up to 4 images or a single video. threadItems creates a reply chain (Bluesky thread). Images exceeding 1MB are automatically compressed. Alt text supported via mediaItem properties.
|
|
6194
|
+
Bluesky post settings. Supports text posts with up to 4 images or a single video. threadItems creates a reply chain (Bluesky thread). Images exceeding 1MB are automatically compressed. Alt text supported via mediaItem properties. Use langs to tag post language for feed-generator filtering.
|
|
5670
6195
|
|
|
5671
6196
|
DiscordPlatformData:
|
|
5672
6197
|
type: object
|
|
@@ -5916,7 +6441,7 @@ components:
|
|
|
5916
6441
|
_id: { type: string }
|
|
5917
6442
|
platform:
|
|
5918
6443
|
type: string
|
|
5919
|
-
enum: [tiktok, instagram, facebook, youtube, linkedin, twitter, threads, pinterest, reddit, bluesky, googlebusiness, telegram, snapchat, discord, slack, whatsapp, linkedinads, metaads, pinterestads, tiktokads, xads, googleads, openaiads]
|
|
6444
|
+
enum: [tiktok, instagram, facebook, youtube, linkedin, twitter, threads, pinterest, reddit, bluesky, googlebusiness, telegram, snapchat, discord, slack, whatsapp, linkedinads, metaads, pinterestads, tiktokads, xads, googleads, openaiads, sms, phone, rcs]
|
|
5920
6445
|
profileId:
|
|
5921
6446
|
oneOf:
|
|
5922
6447
|
- type: string
|
|
@@ -6083,12 +6608,18 @@ components:
|
|
|
6083
6608
|
properties:
|
|
6084
6609
|
billingSystem:
|
|
6085
6610
|
type: string
|
|
6086
|
-
enum: [metronome, stripe]
|
|
6611
|
+
enum: [metronome, stripe, shopify]
|
|
6087
6612
|
plan:
|
|
6088
6613
|
type: object
|
|
6089
6614
|
properties:
|
|
6090
6615
|
name: { type: string }
|
|
6091
6616
|
isUsageBased: { type: boolean }
|
|
6617
|
+
isPaid:
|
|
6618
|
+
type: boolean
|
|
6619
|
+
description: 'True when the key belongs to an account with an active paid billing relationship (Stripe subscription, Metronome enrollment, or Shopify-managed billing).'
|
|
6620
|
+
shopifyShopDomain:
|
|
6621
|
+
type: [string, "null"]
|
|
6622
|
+
description: 'myshopify.com domain owning the subscription; present only when billingSystem is shopify.'
|
|
6092
6623
|
period:
|
|
6093
6624
|
type: object
|
|
6094
6625
|
description: Current billing cycle. `start`/`end` are resolved for usage-based accounts only.
|
|
@@ -6418,14 +6949,14 @@ components:
|
|
|
6418
6949
|
likes: { type: integer, example: 0 }
|
|
6419
6950
|
comments: { type: integer, example: 0 }
|
|
6420
6951
|
shares: { type: integer, example: 0 }
|
|
6421
|
-
saves: { type: integer, example: 0, description: 'Number of saves/bookmarks (Instagram, Pinterest)' }
|
|
6952
|
+
saves: { type: integer, example: 0, description: 'Number of saves/bookmarks (Instagram, Pinterest, X/Twitter)' }
|
|
6422
6953
|
clicks: { type: integer, example: 0 }
|
|
6423
6954
|
views: { type: integer, example: 0 }
|
|
6424
6955
|
follows: { type: integer, example: 0, description: 'Instagram feed posts and stories only: organic accounts that started following from this post. 0 for reels and other platforms.' }
|
|
6425
6956
|
igReelsAvgWatchTime: { type: integer, example: 0, description: 'Instagram Reels only: average watch time per play, in milliseconds. 0 for non-Reels media and other platforms.' }
|
|
6426
6957
|
igReelsVideoViewTotalTime: { type: integer, example: 0, description: 'Instagram Reels only: total watch time including replays, in milliseconds. 0 for non-Reels media and other platforms.' }
|
|
6427
6958
|
videoDurationSeconds: { type: [integer, "null"], example: 30, description: 'Video length in seconds. Currently Instagram Reels only; combine with igReelsAvgWatchTime (ms) to estimate retention. Null when unknown (other platforms, non-video media, or when Instagram does not expose the media URL, e.g. reels with copyrighted audio).' }
|
|
6428
|
-
engagementRate: { type: number, example:
|
|
6959
|
+
engagementRate: { type: number, example: 6.59, description: 'Percentage, rounded to 2 decimals: (likes + comments + shares + saves) / (impressions or reach or views) * 100. Clicks and follows are never counted. The denominator is the FIRST of impressions, reach, views that is non-zero, so it is not the same basis on every post: a post with impressions divides by impressions, one without falls back to reach, then to views. If you need a single consistent basis (e.g. interactions / reach), compute it from the raw fields above. The engagementRate on the LinkedIn account endpoints is a different formula.' }
|
|
6429
6960
|
lastUpdated: { type: string, format: date-time }
|
|
6430
6961
|
PlatformAnalytics:
|
|
6431
6962
|
type: object
|
|
@@ -6483,11 +7014,26 @@ components:
|
|
|
6483
7014
|
type: object
|
|
6484
7015
|
properties:
|
|
6485
7016
|
type: { type: string, enum: [image, video] }
|
|
6486
|
-
url:
|
|
6487
|
-
|
|
7017
|
+
url:
|
|
7018
|
+
type: [string, "null"]
|
|
7019
|
+
format: uri
|
|
7020
|
+
description: >-
|
|
7021
|
+
'Direct URL to the media file. Null when the platform withholds it: check
|
|
7022
|
+
mediaStatus before downloading. Instagram omits the video file for Reels it
|
|
7023
|
+
flags as containing copyrighted material (its docs name audio as the usual
|
|
7024
|
+
cause), so type stays "video" while the file is permanently unreachable.'
|
|
7025
|
+
thumbnail: { type: [string, "null"], format: uri, description: 'Thumbnail URL (same as url for images). Still present when url is null.' }
|
|
6488
7026
|
altText:
|
|
6489
7027
|
type: string
|
|
6490
7028
|
description: Accessibility alt text set on the media, when present.
|
|
7029
|
+
mediaStatus:
|
|
7030
|
+
type: string
|
|
7031
|
+
enum: [available, unavailable]
|
|
7032
|
+
description: 'unavailable means the media file could not be retrieved (url is null or, for LinkedIn videos, a cover image standing in for the file). available or absent means the file is available at url (older synced items omit the field).'
|
|
7033
|
+
unavailableReason:
|
|
7034
|
+
type: string
|
|
7035
|
+
enum: [platform_withheld]
|
|
7036
|
+
description: 'Why the file is missing. platform_withheld means the platform declined to return it and retrying will not help.'
|
|
6491
7037
|
AnalyticsListResponse:
|
|
6492
7038
|
type: object
|
|
6493
7039
|
properties:
|
|
@@ -6563,7 +7109,7 @@ components:
|
|
|
6563
7109
|
shares: { type: integer, description: Total reshares across all posts }
|
|
6564
7110
|
saves: { type: integer, description: Total times posts were saved (personal accounts only) }
|
|
6565
7111
|
sends: { type: integer, description: Total times posts were sent via LinkedIn messaging (personal accounts only) }
|
|
6566
|
-
engagementRate: { type: number, description: Overall engagement rate as percentage }
|
|
7112
|
+
engagementRate: { type: number, description: 'Overall engagement rate, as a percentage rounded to 2 decimals: (reactions + comments + shares + saves + sends) / impressions * 100. Clicks are not counted, and there is no fallback denominator, so this is 0 whenever impressions is 0. This is NOT the same formula as PostAnalytics.engagementRate on GET /v1/analytics.' }
|
|
6567
7113
|
note: { type: string }
|
|
6568
7114
|
lastUpdated: { type: string, format: date-time }
|
|
6569
7115
|
LinkedInAggregateAnalyticsDailyResponse:
|
|
@@ -7011,7 +7557,7 @@ components:
|
|
|
7011
7557
|
type: object
|
|
7012
7558
|
additionalProperties:
|
|
7013
7559
|
type: integer
|
|
7014
|
-
description: "Per-action-type counts summed over the date range, keyed by the platform's action-type names. Meta: raw Insights action_type keys (link_click, offsite_conversion.fb_pixel_purchase, onsite_conversion.lead_grouped, ...) — both engagement and conversion events. X: conversion types (purchase, sign_up, site_visit, download, custom). LinkedIn: conversion types (post_click, post_view, lead_gen). Google returns {} (its per-action names aren't synced per ad). Empty object when no actions are reported. NOTE: keys differ by platform, so branch on the ad's platform when interpreting them."
|
|
7560
|
+
description: "Per-action-type counts summed over the date range, keyed by the platform's action-type names. Meta: raw Insights action_type keys (link_click, offsite_conversion.fb_pixel_purchase, onsite_conversion.lead_grouped, ...) — both engagement and conversion events. TikTok: pixel conversions (purchase, add_to_cart, initiate_checkout, view_content, complete_payment, lead) plus the paid-engagement family (follow, post_reaction for paid likes, comment, share) — follow is how FOLLOWERS-goal campaigns report their result. X: conversion types (purchase, sign_up, site_visit, download, custom). LinkedIn: conversion types (post_click, post_view, lead_gen). Google returns {} (its per-action names aren't synced per ad). Empty object when no actions are reported. NOTE: keys differ by platform, so branch on the ad's platform when interpreting them."
|
|
7015
7561
|
example:
|
|
7016
7562
|
link_click: 160
|
|
7017
7563
|
post_engagement: 300
|
|
@@ -7108,13 +7654,17 @@ components:
|
|
|
7108
7654
|
Use these fields when you need a specific interaction, and `engagement`
|
|
7109
7655
|
only as the coarse total it has always been.
|
|
7110
7656
|
|
|
7111
|
-
Meta
|
|
7657
|
+
Populated for Meta and, since 2026-08, TikTok (`reactions` = paid
|
|
7658
|
+
likes, `comments`, `shares`; TikTok's `follow` count lives in
|
|
7659
|
+
`actions.follow`, not here). Other platforms leave these at 0.
|
|
7660
|
+
TikTok history note: paused TikTok ads are not re-synced, so
|
|
7661
|
+
campaigns that ended before the rollout keep 0s here.
|
|
7112
7662
|
properties:
|
|
7113
|
-
postEngagement: { type: integer, description: "Meta's own post-engagement total (`post_engagement`)." }
|
|
7114
|
-
pageEngagement: { type: integer, description: "Meta's own page-engagement total (`page_engagement`)." }
|
|
7115
|
-
reactions: { type: integer, description: "Reactions on the ad's post (`post_reaction`)." }
|
|
7663
|
+
postEngagement: { type: integer, description: "Meta's own post-engagement total (`post_engagement`). Meta-only." }
|
|
7664
|
+
pageEngagement: { type: integer, description: "Meta's own page-engagement total (`page_engagement`). Meta-only." }
|
|
7665
|
+
reactions: { type: integer, description: "Reactions on the ad's post (`post_reaction`). For TikTok these are its paid likes." }
|
|
7116
7666
|
comments: { type: integer, description: "Comments on the ad's post." }
|
|
7117
|
-
shares: { type: integer, description: "Shares of the ad's post. Meta reports these under the action type literally named `post`." }
|
|
7667
|
+
shares: { type: integer, description: "Shares of the ad's post. Meta reports these under the action type literally named `post`; TikTok under `share`." }
|
|
7118
7668
|
saves: { type: integer, description: "Saves of the ad's post (`onsite_conversion.post_save`)." }
|
|
7119
7669
|
pageLikes: { type: integer, description: "New Page likes attributed to the ad (`like`)." }
|
|
7120
7670
|
videoViews: { type: integer, description: "3-second video views (`video_view`). For completion-based counts use `videoThruplayWatchedActions`." }
|
|
@@ -7605,6 +8155,7 @@ components:
|
|
|
7605
8155
|
imageUrl: { type: string, description: Alternative image URL }
|
|
7606
8156
|
videoId: { type: [string, "null"], description: "Meta video ID for VIDEO-type ads. Null for non-video ads. Callers that need an embeddable MP4 can call GET /{videoId}?fields=source with the page access token." }
|
|
7607
8157
|
videoUrl: { type: [string, "null"], description: "Public Facebook watch URL for VIDEO-type ads (https://www.facebook.com/watch/?v={videoId}). Null for non-video ads." }
|
|
8158
|
+
creativeId: { type: [string, "null"], description: "Meta ad creative id backing this ad. Reusable via existingCreativeId on POST /v1/ads/create." }
|
|
7608
8159
|
objectType: { type: string, description: "Meta creative object_type (e.g. SHARE, VIDEO, PRIVACY_CHECK_FAIL, POST_DELETED). Use this to render state-aware previews — when Meta moderation strips image/video fields, only thumbnailUrl at 64x64 is available." }
|
|
7609
8160
|
objectStoryId: { type: [string, "null"], description: "Meta creative `object_story_id` (the SHARE reference). Frequently absent — Meta omits it for SHARE creatives. Use effectiveObjectStoryId instead." }
|
|
7610
8161
|
effectiveObjectStoryId: { type: [string, "null"], description: "Meta `effective_object_story_id` — `{pageId}_{postId}` of the Facebook post the ad's engagement (comments) lives on. Pass to GET /v1/ads?effectiveObjectStoryId= to map a Business-Manager-visible post back to this ad; GET /v1/ads/{adId}/comments resolves comments against it." }
|
|
@@ -7762,7 +8313,7 @@ components:
|
|
|
7762
8313
|
profileId: { type: string }
|
|
7763
8314
|
advertisingChannelType:
|
|
7764
8315
|
type: [string, "null"]
|
|
7765
|
-
description: "Google-only. Raw campaign.advertising_channel_type (SEARCH, PERFORMANCE_MAX, VIDEO, DEMAND_GEN, DISPLAY, SHOPPING, ...). Serving surface, distinct from platformObjective (advertiser intent). Null/absent for non-Google platforms."
|
|
8316
|
+
description: "Google-only. Raw campaign.advertising_channel_type (SEARCH, PERFORMANCE_MAX, LOCAL_SERVICES, VIDEO, DEMAND_GEN, DISPLAY, SHOPPING, ...). Serving surface, distinct from platformObjective (advertiser intent). Null/absent for non-Google platforms."
|
|
7766
8317
|
platformObjective: { type: [string, "null"], description: "Raw Meta campaign objective (e.g. OUTCOME_SALES, OUTCOME_LEADS, OUTCOME_TRAFFIC)" }
|
|
7767
8318
|
optimizationGoal:
|
|
7768
8319
|
type: [string, "null"]
|
|
@@ -8065,6 +8616,37 @@ components:
|
|
|
8065
8616
|
customConversionId: { type: string, description: "Drops straight into promotedObject.customConversionId on POST /v1/ads/create." }
|
|
8066
8617
|
reused: { type: boolean, description: "True when an existing conversion matched name + pixelId; the response is then a 200." }
|
|
8067
8618
|
customConversion: { $ref: '#/components/schemas/CustomConversion' }
|
|
8619
|
+
Blog:
|
|
8620
|
+
type: object
|
|
8621
|
+
description: 'A blog container on the connected platform. All content lives on the platform; Zernio proxies it and stores nothing.'
|
|
8622
|
+
properties:
|
|
8623
|
+
id: { type: string, description: 'Platform-native blog id (numeric string for Shopify).' }
|
|
8624
|
+
platform: { type: string, enum: [shopify] }
|
|
8625
|
+
title: { type: string }
|
|
8626
|
+
handle: { type: string, description: 'URL slug of the blog.' }
|
|
8627
|
+
BlogArticle:
|
|
8628
|
+
type: object
|
|
8629
|
+
description: 'An article inside a blog on the connected platform.'
|
|
8630
|
+
properties:
|
|
8631
|
+
id: { type: string, description: 'Platform-native article id (numeric string for Shopify).' }
|
|
8632
|
+
blogId: { type: string, description: 'Platform-native id of the blog the article belongs to.' }
|
|
8633
|
+
platform: { type: string, enum: [shopify] }
|
|
8634
|
+
title: { type: string }
|
|
8635
|
+
bodyHtml: { type: [string, "null"], description: 'Article body as HTML.' }
|
|
8636
|
+
handle: { type: string, description: 'URL slug of the article.' }
|
|
8637
|
+
tags: { type: array, items: { type: string } }
|
|
8638
|
+
author: { type: [string, "null"], description: 'Display name of the article author.' }
|
|
8639
|
+
excerpt: { type: [string, "null"], description: 'Short summary shown in blog listings.' }
|
|
8640
|
+
image:
|
|
8641
|
+
type: [object, "null"]
|
|
8642
|
+
description: Featured image.
|
|
8643
|
+
properties:
|
|
8644
|
+
url: { type: string }
|
|
8645
|
+
altText: { type: [string, "null"] }
|
|
8646
|
+
isPublished: { type: boolean, description: 'False while the article is a draft or its publish date is still in the future.' }
|
|
8647
|
+
publishedAt: { type: [string, "null"], format: date-time, description: 'When the article was (or is scheduled to be) published; null for drafts.' }
|
|
8648
|
+
createdAt: { type: [string, "null"], format: date-time }
|
|
8649
|
+
updatedAt: { type: [string, "null"], format: date-time }
|
|
8068
8650
|
TrackingTag:
|
|
8069
8651
|
type: object
|
|
8070
8652
|
description: |
|
|
@@ -8594,6 +9176,31 @@ webhooks:
|
|
|
8594
9176
|
responses:
|
|
8595
9177
|
'200':
|
|
8596
9178
|
description: Webhook received successfully
|
|
9179
|
+
referral.received:
|
|
9180
|
+
post:
|
|
9181
|
+
operationId: onReferralReceived
|
|
9182
|
+
summary: Referral received event
|
|
9183
|
+
description: |
|
|
9184
|
+
Fired when someone opens an EXISTING Instagram or Messenger thread
|
|
9185
|
+
through an attributable entry point - an ig.me / m.me link with a
|
|
9186
|
+
`ref` parameter, or (Messenger) a returning Click-to-Message ad click -
|
|
9187
|
+
which Meta delivers as a standalone referral with no message attached.
|
|
9188
|
+
A referral that rides an inbound message (first message of a thread,
|
|
9189
|
+
icebreaker taps, returning ad clicks on Instagram) arrives on
|
|
9190
|
+
`message.received` under `metadata.referral` instead; the two never
|
|
9191
|
+
fire for the same click. The first referral captured on a conversation
|
|
9192
|
+
is also persisted on it (see `metadata` on `GET
|
|
9193
|
+
/v1/inbox/conversations`). Requires the Inbox add-on.
|
|
9194
|
+
tags: [Webhook Events]
|
|
9195
|
+
requestBody:
|
|
9196
|
+
required: true
|
|
9197
|
+
content:
|
|
9198
|
+
application/json:
|
|
9199
|
+
schema:
|
|
9200
|
+
$ref: '#/components/schemas/WebhookPayloadReferral'
|
|
9201
|
+
responses:
|
|
9202
|
+
'200':
|
|
9203
|
+
description: Webhook received successfully
|
|
8597
9204
|
comment.received:
|
|
8598
9205
|
post:
|
|
8599
9206
|
operationId: onCommentReceived
|
|
@@ -8839,6 +9446,28 @@ webhooks:
|
|
|
8839
9446
|
responses:
|
|
8840
9447
|
'200':
|
|
8841
9448
|
description: Webhook received successfully
|
|
9449
|
+
whatsapp.template.category_updated:
|
|
9450
|
+
post:
|
|
9451
|
+
operationId: onWhatsAppTemplateCategoryUpdated
|
|
9452
|
+
summary: WhatsApp template category updated event
|
|
9453
|
+
description: |
|
|
9454
|
+
Fired when Meta reclassifies a WhatsApp Business template's category
|
|
9455
|
+
after approval. Forwarded from Meta's `template_category_update`
|
|
9456
|
+
webhook field on the WhatsApp Business Account. Category drives
|
|
9457
|
+
Meta's per-conversation tariff and whether the template is subject
|
|
9458
|
+
to the recipient's marketing opt-out. `template.changeType` is
|
|
9459
|
+
`scheduled` (24h advance notice) or `applied`; `template.category`
|
|
9460
|
+
is always the category right now.
|
|
9461
|
+
tags: [Webhook Events]
|
|
9462
|
+
requestBody:
|
|
9463
|
+
required: true
|
|
9464
|
+
content:
|
|
9465
|
+
application/json:
|
|
9466
|
+
schema:
|
|
9467
|
+
$ref: '#/components/schemas/WebhookPayloadWhatsAppTemplateCategoryUpdated'
|
|
9468
|
+
responses:
|
|
9469
|
+
'200':
|
|
9470
|
+
description: Webhook received successfully
|
|
8842
9471
|
whatsapp.automatic_event:
|
|
8843
9472
|
post:
|
|
8844
9473
|
operationId: onWhatsAppAutomaticEvent
|
|
@@ -8862,7 +9491,10 @@ webhooks:
|
|
|
8862
9491
|
properties:
|
|
8863
9492
|
id: { type: string }
|
|
8864
9493
|
event: { type: string, enum: [whatsapp.automatic_event] }
|
|
8865
|
-
timestamp:
|
|
9494
|
+
timestamp:
|
|
9495
|
+
type: string
|
|
9496
|
+
format: date-time
|
|
9497
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
8866
9498
|
accountId:
|
|
8867
9499
|
type: string
|
|
8868
9500
|
description: SocialAccount id of the WhatsApp number whose conversation was flagged.
|
|
@@ -8907,7 +9539,10 @@ webhooks:
|
|
|
8907
9539
|
properties:
|
|
8908
9540
|
id: { type: string }
|
|
8909
9541
|
event: { type: string, enum: [whatsapp.number.activated] }
|
|
8910
|
-
timestamp:
|
|
9542
|
+
timestamp:
|
|
9543
|
+
type: string
|
|
9544
|
+
format: date-time
|
|
9545
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
8911
9546
|
number:
|
|
8912
9547
|
type: object
|
|
8913
9548
|
properties:
|
|
@@ -8936,7 +9571,10 @@ webhooks:
|
|
|
8936
9571
|
properties:
|
|
8937
9572
|
id: { type: string }
|
|
8938
9573
|
event: { type: string, enum: [whatsapp.number.declined] }
|
|
8939
|
-
timestamp:
|
|
9574
|
+
timestamp:
|
|
9575
|
+
type: string
|
|
9576
|
+
format: date-time
|
|
9577
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
8940
9578
|
number:
|
|
8941
9579
|
type: object
|
|
8942
9580
|
properties:
|
|
@@ -8968,7 +9606,10 @@ webhooks:
|
|
|
8968
9606
|
properties:
|
|
8969
9607
|
id: { type: string }
|
|
8970
9608
|
event: { type: string, enum: [whatsapp.number.action_required] }
|
|
8971
|
-
timestamp:
|
|
9609
|
+
timestamp:
|
|
9610
|
+
type: string
|
|
9611
|
+
format: date-time
|
|
9612
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
8972
9613
|
reason: { type: string }
|
|
8973
9614
|
number:
|
|
8974
9615
|
type: object
|
|
@@ -8998,7 +9639,10 @@ webhooks:
|
|
|
8998
9639
|
properties:
|
|
8999
9640
|
id: { type: string }
|
|
9000
9641
|
event: { type: string, enum: [whatsapp.number.verification_required] }
|
|
9001
|
-
timestamp:
|
|
9642
|
+
timestamp:
|
|
9643
|
+
type: string
|
|
9644
|
+
format: date-time
|
|
9645
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
9002
9646
|
number:
|
|
9003
9647
|
type: object
|
|
9004
9648
|
properties:
|
|
@@ -9029,7 +9673,10 @@ webhooks:
|
|
|
9029
9673
|
properties:
|
|
9030
9674
|
id: { type: string }
|
|
9031
9675
|
event: { type: string, enum: [whatsapp.number.suspended] }
|
|
9032
|
-
timestamp:
|
|
9676
|
+
timestamp:
|
|
9677
|
+
type: string
|
|
9678
|
+
format: date-time
|
|
9679
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
9033
9680
|
number:
|
|
9034
9681
|
type: object
|
|
9035
9682
|
properties:
|
|
@@ -9058,7 +9705,10 @@ webhooks:
|
|
|
9058
9705
|
properties:
|
|
9059
9706
|
id: { type: string }
|
|
9060
9707
|
event: { type: string, enum: [whatsapp.number.reactivated] }
|
|
9061
|
-
timestamp:
|
|
9708
|
+
timestamp:
|
|
9709
|
+
type: string
|
|
9710
|
+
format: date-time
|
|
9711
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
9062
9712
|
number:
|
|
9063
9713
|
type: object
|
|
9064
9714
|
properties:
|
|
@@ -9087,7 +9737,10 @@ webhooks:
|
|
|
9087
9737
|
properties:
|
|
9088
9738
|
id: { type: string }
|
|
9089
9739
|
event: { type: string, enum: [whatsapp.number.released] }
|
|
9090
|
-
timestamp:
|
|
9740
|
+
timestamp:
|
|
9741
|
+
type: string
|
|
9742
|
+
format: date-time
|
|
9743
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
9091
9744
|
number:
|
|
9092
9745
|
type: object
|
|
9093
9746
|
properties:
|
|
@@ -9118,7 +9771,10 @@ webhooks:
|
|
|
9118
9771
|
properties:
|
|
9119
9772
|
id: { type: string }
|
|
9120
9773
|
event: { type: string, enum: [whatsapp.number.kyc_submitted, verification.approved, verification.failed] }
|
|
9121
|
-
timestamp:
|
|
9774
|
+
timestamp:
|
|
9775
|
+
type: string
|
|
9776
|
+
format: date-time
|
|
9777
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
9122
9778
|
number:
|
|
9123
9779
|
type: object
|
|
9124
9780
|
properties:
|
|
@@ -9146,7 +9802,10 @@ webhooks:
|
|
|
9146
9802
|
properties:
|
|
9147
9803
|
id: { type: string }
|
|
9148
9804
|
event: { type: string, enum: [verification.approved] }
|
|
9149
|
-
timestamp:
|
|
9805
|
+
timestamp:
|
|
9806
|
+
type: string
|
|
9807
|
+
format: date-time
|
|
9808
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
9150
9809
|
verification:
|
|
9151
9810
|
type: object
|
|
9152
9811
|
properties:
|
|
@@ -9173,7 +9832,10 @@ webhooks:
|
|
|
9173
9832
|
properties:
|
|
9174
9833
|
id: { type: string }
|
|
9175
9834
|
event: { type: string, enum: [verification.failed] }
|
|
9176
|
-
timestamp:
|
|
9835
|
+
timestamp:
|
|
9836
|
+
type: string
|
|
9837
|
+
format: date-time
|
|
9838
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.'
|
|
9177
9839
|
verification:
|
|
9178
9840
|
type: object
|
|
9179
9841
|
properties:
|
|
@@ -12821,7 +13483,7 @@ paths:
|
|
|
12821
13483
|
lastVerified: "2026-03-26"
|
|
12822
13484
|
tiers:
|
|
12823
13485
|
- { tier: x_api_005, pricePerCallUsd: 0.005, operationCount: 13 }
|
|
12824
|
-
- { tier: x_api_010, pricePerCallUsd: 0.010, operationCount:
|
|
13486
|
+
- { tier: x_api_010, pricePerCallUsd: 0.010, operationCount: 10 }
|
|
12825
13487
|
- { tier: x_api_015, pricePerCallUsd: 0.015, operationCount: 3 }
|
|
12826
13488
|
- { tier: x_api_200, pricePerCallUsd: 0.200, operationCount: 1 }
|
|
12827
13489
|
operations:
|
|
@@ -12851,6 +13513,22 @@ paths:
|
|
|
12851
13513
|
tier: x_api_200
|
|
12852
13514
|
triggeredBy:
|
|
12853
13515
|
- { method: publishPost, metering: always }
|
|
13516
|
+
- operation: article_draft
|
|
13517
|
+
eventType: x_article_draft
|
|
13518
|
+
displayName: "X API: Article Draft"
|
|
13519
|
+
pricePerCallUsd: 0.010
|
|
13520
|
+
pricePerCallCents: 1.0
|
|
13521
|
+
tier: x_api_010
|
|
13522
|
+
triggeredBy:
|
|
13523
|
+
- { method: createArticleDraft, metering: always }
|
|
13524
|
+
- operation: article_publish
|
|
13525
|
+
eventType: x_article_publish
|
|
13526
|
+
displayName: "X API: Article Publish"
|
|
13527
|
+
pricePerCallUsd: 0.010
|
|
13528
|
+
pricePerCallCents: 1.0
|
|
13529
|
+
tier: x_api_010
|
|
13530
|
+
triggeredBy:
|
|
13531
|
+
- { method: publishArticle, metering: always }
|
|
12854
13532
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
12855
13533
|
/v1/usage:
|
|
12856
13534
|
get:
|
|
@@ -13296,7 +13974,7 @@ paths:
|
|
|
13296
13974
|
summary: Create post
|
|
13297
13975
|
description: |
|
|
13298
13976
|
Create and optionally publish a post. Immediate posts (`publishNow: true`) include `platformPostUrl` in the response.
|
|
13299
|
-
Content is optional when media is attached
|
|
13977
|
+
Content is optional when media is attached, all platforms have `customContent`, every platform entry is an X Article (`platformSpecificData.article`), or every platform entry is a LinkedIn plain repost (`platformSpecificData.reshareUrl` with no text). See each platform's schema for media constraints.
|
|
13300
13978
|
|
|
13301
13979
|
## Idempotency
|
|
13302
13980
|
|
|
@@ -13330,7 +14008,7 @@ paths:
|
|
|
13330
14008
|
title: { type: string }
|
|
13331
14009
|
content:
|
|
13332
14010
|
type: string
|
|
13333
|
-
description: Post caption/text. Optional when media is attached
|
|
14011
|
+
description: 'Post caption/text. Optional when media is attached, all platforms have customContent, every platform entry is an X Article (platformSpecificData.article), or every platform entry is a LinkedIn plain repost (platformSpecificData.reshareUrl with no text). Required for other text-only posts.'
|
|
13334
14012
|
mediaItems:
|
|
13335
14013
|
type: array
|
|
13336
14014
|
items: { $ref: '#/components/schemas/MediaItem' }
|
|
@@ -13408,6 +14086,69 @@ paths:
|
|
|
13408
14086
|
Only used when queuedFromProfile is also provided.
|
|
13409
14087
|
If omitted, uses the profile's default queue.
|
|
13410
14088
|
examples:
|
|
14089
|
+
twitterArticle:
|
|
14090
|
+
summary: Publish a long-form X Article
|
|
14091
|
+
description: |
|
|
14092
|
+
Creates an X Article draft and publishes it. This normally makes two
|
|
14093
|
+
billable X API calls at $0.010 each ($0.020 total). The account must
|
|
14094
|
+
be eligible for X Articles (X Premium+). Article media is supplied as
|
|
14095
|
+
public URLs; Zernio uploads it to X and builds the native media shape.
|
|
14096
|
+
value:
|
|
14097
|
+
platforms:
|
|
14098
|
+
- platform: twitter
|
|
14099
|
+
accountId: "64e1f0a9e2b5af0012ab34cd"
|
|
14100
|
+
platformSpecificData:
|
|
14101
|
+
article:
|
|
14102
|
+
title: "Building a better publishing workflow"
|
|
14103
|
+
mode: publish
|
|
14104
|
+
cover:
|
|
14105
|
+
url: "https://cdn.example.com/article-cover.jpg"
|
|
14106
|
+
content_state:
|
|
14107
|
+
blocks:
|
|
14108
|
+
- type: header-one
|
|
14109
|
+
text: "A reliable publishing workflow"
|
|
14110
|
+
- type: unstyled
|
|
14111
|
+
text: "Long-form publishing should be observable. Read the implementation notes."
|
|
14112
|
+
inline_style_ranges:
|
|
14113
|
+
- { offset: 0, length: 9, style: bold }
|
|
14114
|
+
entity_ranges:
|
|
14115
|
+
- { key: 0, offset: 52, length: 20 }
|
|
14116
|
+
- type: atomic
|
|
14117
|
+
text: " "
|
|
14118
|
+
entity_ranges:
|
|
14119
|
+
- { key: 1, offset: 0, length: 1 }
|
|
14120
|
+
entities:
|
|
14121
|
+
- key: "0"
|
|
14122
|
+
value:
|
|
14123
|
+
type: link
|
|
14124
|
+
mutability: mutable
|
|
14125
|
+
data:
|
|
14126
|
+
url: "https://example.com/implementation-notes"
|
|
14127
|
+
- key: "1"
|
|
14128
|
+
value:
|
|
14129
|
+
type: image
|
|
14130
|
+
mutability: immutable
|
|
14131
|
+
data:
|
|
14132
|
+
url: "https://cdn.example.com/workflow.png"
|
|
14133
|
+
caption: "The publishing stages"
|
|
14134
|
+
publishNow: true
|
|
14135
|
+
twitterArticleDraft:
|
|
14136
|
+
summary: Save an X Article as a platform draft
|
|
14137
|
+
description: Creates only the X Article draft ($0.010) and does not publish it publicly.
|
|
14138
|
+
value:
|
|
14139
|
+
platforms:
|
|
14140
|
+
- platform: twitter
|
|
14141
|
+
accountId: "64e1f0a9e2b5af0012ab34cd"
|
|
14142
|
+
platformSpecificData:
|
|
14143
|
+
article:
|
|
14144
|
+
title: "Draft product update"
|
|
14145
|
+
mode: draft
|
|
14146
|
+
content_state:
|
|
14147
|
+
blocks:
|
|
14148
|
+
- type: unstyled
|
|
14149
|
+
text: "This Article is ready for final review."
|
|
14150
|
+
entities: []
|
|
14151
|
+
publishNow: true
|
|
13411
14152
|
facebookDraft:
|
|
13412
14153
|
summary: Facebook draft post (visible in Publishing Tools)
|
|
13413
14154
|
value:
|
|
@@ -13421,7 +14162,7 @@ paths:
|
|
|
13421
14162
|
facebookCarousel:
|
|
13422
14163
|
summary: Facebook multi-link carousel post
|
|
13423
14164
|
description: |
|
|
13424
|
-
Posts a 2-
|
|
14165
|
+
Posts a 2-10 card carousel where each image has its own click-through link
|
|
13425
14166
|
and optional headline. mediaItems and carouselCards must have the same
|
|
13426
14167
|
length, in the same order. Images only (no video cards).
|
|
13427
14168
|
value:
|
|
@@ -15270,7 +16011,15 @@ paths:
|
|
|
15270
16011
|
operationId: getAccountHealth
|
|
15271
16012
|
tags: [Accounts]
|
|
15272
16013
|
summary: Check account health
|
|
15273
|
-
description:
|
|
16014
|
+
description: |
|
|
16015
|
+
Returns detailed health info for a specific account including token status, permissions, and recommendations.
|
|
16016
|
+
|
|
16017
|
+
For WhatsApp accounts the response also includes `platformConnection`, a live probe of the
|
|
16018
|
+
Meta link behind the channel (the same read as `GET /v1/whatsapp/number-info`). The OAuth
|
|
16019
|
+
token can be perfectly valid while Meta refuses to serve the phone-number object (for
|
|
16020
|
+
example after a phone-side coexistence disconnect), so `tokenStatus` alone is not a
|
|
16021
|
+
liveness signal for WhatsApp. When the Meta link is dead, `platformConnection.status` is
|
|
16022
|
+
`disconnected` and the overall `status` is `error`.
|
|
15274
16023
|
parameters:
|
|
15275
16024
|
- name: accountId
|
|
15276
16025
|
in: path
|
|
@@ -15338,6 +16087,28 @@ paths:
|
|
|
15338
16087
|
type: array
|
|
15339
16088
|
items: { type: string }
|
|
15340
16089
|
description: Actionable recommendations to fix issues
|
|
16090
|
+
platformConnection:
|
|
16091
|
+
type: object
|
|
16092
|
+
description: 'WhatsApp accounts only. Live probe of the Meta link behind the channel, performed at request time (the same read as GET /v1/whatsapp/number-info).'
|
|
16093
|
+
properties:
|
|
16094
|
+
status:
|
|
16095
|
+
type: string
|
|
16096
|
+
enum: [connected, disconnected, unknown]
|
|
16097
|
+
description: '`connected` = Meta served the channel object. `disconnected` = Meta refused to serve it (Graph error 100, subcode 33), which is how a phone-side coexistence disconnect surfaces. `unknown` = the live read failed for another reason (timeout, transient Meta error), not evidence either way.'
|
|
16098
|
+
checkedAt:
|
|
16099
|
+
type: string
|
|
16100
|
+
format: date-time
|
|
16101
|
+
description: When this live probe ran (always the current request; never cached)
|
|
16102
|
+
phoneStatus:
|
|
16103
|
+
type: [string, "null"]
|
|
16104
|
+
description: 'Meta''s own `status` field from the phone-number node (for example CONNECTED), when the object was readable'
|
|
16105
|
+
metaError:
|
|
16106
|
+
type: [object, "null"]
|
|
16107
|
+
description: Set only when status is `disconnected`
|
|
16108
|
+
properties:
|
|
16109
|
+
code: { type: integer, description: 'Meta Graph error code (100)' }
|
|
16110
|
+
subcode: { type: integer, description: 'Meta Graph error subcode (33)' }
|
|
16111
|
+
message: { type: string }
|
|
15341
16112
|
example:
|
|
15342
16113
|
accountId: "abc123"
|
|
15343
16114
|
platform: "instagram"
|
|
@@ -15367,6 +16138,7 @@ paths:
|
|
|
15367
16138
|
missingRequired: []
|
|
15368
16139
|
issues: []
|
|
15369
16140
|
recommendations: []
|
|
16141
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
15370
16142
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
15371
16143
|
'404': { $ref: '#/components/responses/NotFound' }
|
|
15372
16144
|
/v1/accounts/{accountId}/follow-status/{userId}:
|
|
@@ -15925,6 +16697,17 @@ paths:
|
|
|
15925
16697
|
`facebook_login`: the Facebook Login dialog, i.e. "Instagram API with Facebook Login". The user authorizes a Facebook Page that has a linked Instagram professional account, and every API call for that account then runs through the Page. Use this when the customer manages Instagram through a Page and expects the Facebook consent screen. Because the user has to pick which Page to connect, the callback continues at the account-selection step, `/v1/connect/instagram/select-account`.
|
|
15926
16698
|
|
|
15927
16699
|
`facebook_login` supports `headless=true` like the other selection platforms: the callback redirects to your `redirect_url` with `profileId`, `tempToken`, `platform=instagram`, `step=select_account` and `connect_token`, which you pass into the select-account endpoints to finish. The default `instagram_login` has no selection step, so it connects the account directly.
|
|
16700
|
+
- name: onboarding
|
|
16701
|
+
in: query
|
|
16702
|
+
schema: { type: string, enum: [api, business_app] }
|
|
16703
|
+
description: |
|
|
16704
|
+
WhatsApp only. Ignored for every other platform. Controls which screen Meta's Embedded Signup popup shows.
|
|
16705
|
+
|
|
16706
|
+
If omitted, the connection defaults to coexistence (same as `business_app` below), preserving existing behavior for numbers already on the WhatsApp Business app.
|
|
16707
|
+
|
|
16708
|
+
`api`: standard Embedded Signup, showing Meta's WABA/number picker. Use this to connect a phone number already on Cloud API elsewhere.
|
|
16709
|
+
|
|
16710
|
+
`business_app`: coexistence, i.e. 'Connect existing WhatsApp Business app' (a number shared between Cloud API and the consumer WhatsApp Business app).
|
|
15928
16711
|
security:
|
|
15929
16712
|
- bearerAuth: []
|
|
15930
16713
|
responses:
|
|
@@ -16121,6 +16904,124 @@ paths:
|
|
|
16121
16904
|
'404':
|
|
16122
16905
|
description: "Profile or posting account not found"
|
|
16123
16906
|
|
|
16907
|
+
/v1/connect/shopify:
|
|
16908
|
+
get:
|
|
16909
|
+
x-resource-group: "accounts"
|
|
16910
|
+
operationId: getShopifyConnectUrl
|
|
16911
|
+
tags: [Connect]
|
|
16912
|
+
summary: Get Shopify OAuth connect URL
|
|
16913
|
+
description: |
|
|
16914
|
+
Initiate the Shopify OAuth flow for a store. Shopify is a connect-only
|
|
16915
|
+
platform: the connected account does not publish social posts, it powers
|
|
16916
|
+
the Blogs API (`/v1/accounts/{accountId}/blogs`). Returns an `authUrl`
|
|
16917
|
+
to redirect the merchant to; after they approve the install, Shopify
|
|
16918
|
+
redirects their browser to Zernio's callback, the account is created on
|
|
16919
|
+
the profile (platform `shopify`), and the browser is redirected to
|
|
16920
|
+
`redirect_url` (or the Zernio dashboard when omitted). Requested scopes
|
|
16921
|
+
are `read_content` and `write_content` (content only; no customer or
|
|
16922
|
+
order data). Connecting the same profile to a store again refreshes the
|
|
16923
|
+
stored token in place.
|
|
16924
|
+
security:
|
|
16925
|
+
- bearerAuth: []
|
|
16926
|
+
parameters:
|
|
16927
|
+
- name: profileId
|
|
16928
|
+
in: query
|
|
16929
|
+
required: true
|
|
16930
|
+
schema: { type: string }
|
|
16931
|
+
description: 'Your Zernio profile ID (get from /v1/profiles).'
|
|
16932
|
+
- name: shop
|
|
16933
|
+
in: query
|
|
16934
|
+
required: true
|
|
16935
|
+
schema: { type: string }
|
|
16936
|
+
description: 'The myshopify.com store domain to connect, e.g. `your-store.myshopify.com` (the bare `your-store` prefix is accepted too).'
|
|
16937
|
+
- name: redirect_url
|
|
16938
|
+
in: query
|
|
16939
|
+
schema: { type: string, format: uri }
|
|
16940
|
+
description: 'Your custom redirect URL after connection completes. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. On failure an `error` query param is appended.'
|
|
16941
|
+
responses:
|
|
16942
|
+
'200':
|
|
16943
|
+
description: OAuth authorization URL to redirect the merchant to
|
|
16944
|
+
content:
|
|
16945
|
+
application/json:
|
|
16946
|
+
schema:
|
|
16947
|
+
type: object
|
|
16948
|
+
properties:
|
|
16949
|
+
authUrl:
|
|
16950
|
+
type: string
|
|
16951
|
+
format: uri
|
|
16952
|
+
description: URL to redirect your user to for OAuth authorization
|
|
16953
|
+
state:
|
|
16954
|
+
type: string
|
|
16955
|
+
description: State parameter for security (handled automatically)
|
|
16956
|
+
'400':
|
|
16957
|
+
description: 'Invalid `profileId` format, `shop` is not a myshopify.com store domain, or `redirect_url` uses a script-executing scheme.'
|
|
16958
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
16959
|
+
'402': { $ref: '#/components/responses/PaymentRequired' }
|
|
16960
|
+
'403':
|
|
16961
|
+
description: 'API key does not have access to this profile.'
|
|
16962
|
+
'404':
|
|
16963
|
+
description: 'Profile not found or access denied.'
|
|
16964
|
+
'500':
|
|
16965
|
+
description: 'Shopify API not configured (missing credentials).'
|
|
16966
|
+
|
|
16967
|
+
/v1/connect/shopify/token:
|
|
16968
|
+
post:
|
|
16969
|
+
x-resource-group: "accounts"
|
|
16970
|
+
operationId: connectShopifyWithToken
|
|
16971
|
+
tags: [Connect]
|
|
16972
|
+
summary: Connect a Shopify store with a custom-app Admin token
|
|
16973
|
+
description: |
|
|
16974
|
+
Token-paste alternative to the OAuth flow: connect a store using the
|
|
16975
|
+
Admin API access token of a custom app the merchant created in their
|
|
16976
|
+
own Shopify admin (Settings → Apps and sales channels → Develop apps,
|
|
16977
|
+
with the `read_content`/`write_content` scopes). Use this when the
|
|
16978
|
+
one-click OAuth connect is unavailable or when your users prefer not
|
|
16979
|
+
to install a third-party app on their store. The token is validated
|
|
16980
|
+
against the store before anything is saved; custom-app tokens do not
|
|
16981
|
+
expire. Connecting the same profile to a store again replaces the
|
|
16982
|
+
stored token in place.
|
|
16983
|
+
security:
|
|
16984
|
+
- bearerAuth: []
|
|
16985
|
+
requestBody:
|
|
16986
|
+
required: true
|
|
16987
|
+
content:
|
|
16988
|
+
application/json:
|
|
16989
|
+
schema:
|
|
16990
|
+
type: object
|
|
16991
|
+
required: [profileId, shop, accessToken]
|
|
16992
|
+
properties:
|
|
16993
|
+
profileId:
|
|
16994
|
+
type: string
|
|
16995
|
+
description: 'Your Zernio profile ID (get from /v1/profiles).'
|
|
16996
|
+
shop:
|
|
16997
|
+
type: string
|
|
16998
|
+
description: 'The myshopify.com store domain, e.g. `your-store.myshopify.com` (the bare `your-store` prefix is accepted too).'
|
|
16999
|
+
accessToken:
|
|
17000
|
+
type: string
|
|
17001
|
+
description: 'Admin API access token of the merchant-created custom app (starts with `shpat_`).'
|
|
17002
|
+
responses:
|
|
17003
|
+
'200':
|
|
17004
|
+
description: Store connected as a platform account
|
|
17005
|
+
content:
|
|
17006
|
+
application/json:
|
|
17007
|
+
schema:
|
|
17008
|
+
type: object
|
|
17009
|
+
properties:
|
|
17010
|
+
account:
|
|
17011
|
+
type: object
|
|
17012
|
+
properties:
|
|
17013
|
+
_id: { type: string }
|
|
17014
|
+
platform: { type: string, enum: [shopify] }
|
|
17015
|
+
username: { type: string, description: 'The myshopify.com domain of the connected store.' }
|
|
17016
|
+
displayName: { type: string }
|
|
17017
|
+
profileId: { type: string }
|
|
17018
|
+
'400':
|
|
17019
|
+
description: 'Invalid `profileId` format, `shop` is not a myshopify.com store domain, or Shopify rejected the access token for that store.'
|
|
17020
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
17021
|
+
'402': { $ref: '#/components/responses/PaymentRequired' }
|
|
17022
|
+
'403':
|
|
17023
|
+
description: 'API key does not have access to this profile.'
|
|
17024
|
+
|
|
16124
17025
|
/v1/connect/tiktok-ads:
|
|
16125
17026
|
patch:
|
|
16126
17027
|
x-resource-group: "accounts"
|
|
@@ -19547,7 +20448,7 @@ paths:
|
|
|
19547
20448
|
'403':
|
|
19548
20449
|
description: Profile limit exceeded for this plan
|
|
19549
20450
|
'409':
|
|
19550
|
-
description: '
|
|
20451
|
+
description: 'Conflict with an existing connection. Either the phone number is a Zernio-provisioned number pinned to a different profile (code WHATSAPP_NUMBER_PINNED_TO_PROFILE, connect it from that profile or move it first with PATCH /v1/whatsapp/phone-numbers/{id}/profile), or the number is already actively connected on another profile or workspace (code WHATSAPP_NUMBER_ALREADY_CONNECTED, disconnect it there first). A number can only be live on one profile.'
|
|
19551
20452
|
|
|
19552
20453
|
/v1/connect/whatsapp/select-phone-number:
|
|
19553
20454
|
get:
|
|
@@ -19704,7 +20605,7 @@ paths:
|
|
|
19704
20605
|
application/json:
|
|
19705
20606
|
schema: { $ref: '#/components/schemas/ErrorResponse' }
|
|
19706
20607
|
'409':
|
|
19707
|
-
description: '
|
|
20608
|
+
description: 'Conflict with an existing connection. Either the phone number is a Zernio-provisioned number pinned to a different profile (code WHATSAPP_NUMBER_PINNED_TO_PROFILE, connect it from that profile or move it first with PATCH /v1/whatsapp/phone-numbers/{id}/profile), or the number is already actively connected on another profile or workspace (code WHATSAPP_NUMBER_ALREADY_CONNECTED, disconnect it there first). A number can only be live on one profile.'
|
|
19708
20609
|
'500':
|
|
19709
20610
|
description: Failed to bind phone number
|
|
19710
20611
|
content:
|
|
@@ -20297,7 +21198,7 @@ paths:
|
|
|
20297
21198
|
sends: { type: integer, description: Times the post was sent via LinkedIn messaging (personal accounts only; 0 for organization accounts) }
|
|
20298
21199
|
clicks: { type: integer, description: Clicks on the post (organization accounts only) }
|
|
20299
21200
|
views: { type: integer, description: Video views (video posts only) }
|
|
20300
|
-
engagementRate: { type: number, description: Engagement rate as percentage }
|
|
21201
|
+
engagementRate: { type: number, description: 'Engagement rate, as a percentage rounded to 2 decimals: (likes + comments + shares + clicks + saves + sends) / impressions * 100. Unlike PostAnalytics.engagementRate on GET /v1/analytics, this one DOES count clicks and has no fallback denominator, so it is 0 whenever impressions is 0. For organization accounts the value is the rate LinkedIn returns, not one computed here.' }
|
|
20301
21202
|
lastUpdated: { type: string, format: date-time }
|
|
20302
21203
|
example:
|
|
20303
21204
|
accountId: "64abc123def456"
|
|
@@ -21811,6 +22712,65 @@ paths:
|
|
|
21811
22712
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
21812
22713
|
'404': { description: Account not found }
|
|
21813
22714
|
|
|
22715
|
+
/v1/accounts/{accountId}/bluesky-settings:
|
|
22716
|
+
get:
|
|
22717
|
+
x-resource-group: "accounts"
|
|
22718
|
+
operationId: getBlueskySettings
|
|
22719
|
+
tags: [Accounts]
|
|
22720
|
+
summary: Get Bluesky account settings
|
|
22721
|
+
description: 'Returns the account''s default post languages (defaultLangs), applied at publish time whenever a post''s platformSpecificData.langs is absent. Null when no default is set.'
|
|
22722
|
+
parameters:
|
|
22723
|
+
- name: accountId
|
|
22724
|
+
in: path
|
|
22725
|
+
required: true
|
|
22726
|
+
schema: { type: string }
|
|
22727
|
+
responses:
|
|
22728
|
+
'200':
|
|
22729
|
+
description: Bluesky account settings
|
|
22730
|
+
content:
|
|
22731
|
+
application/json:
|
|
22732
|
+
schema:
|
|
22733
|
+
type: object
|
|
22734
|
+
properties:
|
|
22735
|
+
defaultLangs:
|
|
22736
|
+
type: [array, "null"]
|
|
22737
|
+
items: { type: string }
|
|
22738
|
+
example: ["pt"]
|
|
22739
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
22740
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
22741
|
+
'404': { description: Account not found }
|
|
22742
|
+
patch:
|
|
22743
|
+
x-resource-group: "accounts"
|
|
22744
|
+
operationId: updateBlueskySettings
|
|
22745
|
+
tags: [Accounts]
|
|
22746
|
+
summary: Update Bluesky account settings
|
|
22747
|
+
description: 'Set or clear the account''s default post languages. 1-3 BCP-47 codes (e.g. "pt", "en-US"), the same validation as per-post langs; explicit null clears the default. Per-post platformSpecificData.langs always overrides this default. Applies to posts published after the change; already-published posts cannot be retagged (Bluesky has no post edit).'
|
|
22748
|
+
parameters:
|
|
22749
|
+
- name: accountId
|
|
22750
|
+
in: path
|
|
22751
|
+
required: true
|
|
22752
|
+
schema: { type: string }
|
|
22753
|
+
requestBody:
|
|
22754
|
+
required: true
|
|
22755
|
+
content:
|
|
22756
|
+
application/json:
|
|
22757
|
+
schema:
|
|
22758
|
+
type: object
|
|
22759
|
+
required: [defaultLangs]
|
|
22760
|
+
properties:
|
|
22761
|
+
defaultLangs:
|
|
22762
|
+
type: [array, "null"]
|
|
22763
|
+
minItems: 1
|
|
22764
|
+
maxItems: 3
|
|
22765
|
+
items: { type: string }
|
|
22766
|
+
example: ["pt"]
|
|
22767
|
+
responses:
|
|
22768
|
+
'200':
|
|
22769
|
+
description: Updated settings
|
|
22770
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
22771
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
22772
|
+
'404': { description: Account not found }
|
|
22773
|
+
|
|
21814
22774
|
/v1/accounts/{accountId}/discord-settings:
|
|
21815
22775
|
get:
|
|
21816
22776
|
x-resource-group: "accounts"
|
|
@@ -23336,7 +24296,7 @@ paths:
|
|
|
23336
24296
|
minItems: 1
|
|
23337
24297
|
items:
|
|
23338
24298
|
type: string
|
|
23339
|
-
enum: [post.scheduled, post.published, post.failed, post.partial, post.cancelled, post.recycled, post.platform.published, post.platform.failed, post.platform.deleted, post.tiktok.url_resolved, post.external.created, post.external.updated, post.external.deleted, account.connected, account.disconnected, account.ads.initial_sync_completed, message.received, conversation.started, call.received, call.ended, call.failed, call.permission_request, message.sent, message.edited, message.deleted, message.delivered, message.read, message.failed, reaction.received, comment.received, review.new, review.updated, lead.received, ad.status_changed, whatsapp.template.status_updated, whatsapp.automatic_event, whatsapp.number.activated, whatsapp.number.declined, whatsapp.number.action_required, whatsapp.number.verification_required, whatsapp.number.suspended, whatsapp.number.reactivated, whatsapp.number.released, whatsapp.number.kyc_submitted, verification.approved, verification.failed]
|
|
24299
|
+
enum: [post.scheduled, post.published, post.failed, post.partial, post.cancelled, post.recycled, post.platform.published, post.platform.failed, post.platform.deleted, post.tiktok.url_resolved, post.external.created, post.external.updated, post.external.deleted, account.connected, account.disconnected, account.ads.initial_sync_completed, message.received, conversation.started, call.received, call.ended, call.failed, call.permission_request, message.sent, message.edited, message.deleted, message.delivered, message.read, message.failed, reaction.received, referral.received, comment.received, review.new, review.updated, lead.received, ad.status_changed, whatsapp.template.status_updated, whatsapp.template.category_updated, whatsapp.automatic_event, whatsapp.number.activated, whatsapp.number.declined, whatsapp.number.action_required, whatsapp.number.verification_required, whatsapp.number.suspended, whatsapp.number.reactivated, whatsapp.number.released, whatsapp.number.kyc_submitted, verification.approved, verification.failed]
|
|
23340
24300
|
description: Events to subscribe to (at least one required)
|
|
23341
24301
|
isActive:
|
|
23342
24302
|
type: boolean
|
|
@@ -23455,7 +24415,7 @@ paths:
|
|
|
23455
24415
|
minItems: 1
|
|
23456
24416
|
items:
|
|
23457
24417
|
type: string
|
|
23458
|
-
enum: [post.scheduled, post.published, post.failed, post.partial, post.cancelled, post.recycled, post.platform.published, post.platform.failed, post.platform.deleted, post.tiktok.url_resolved, post.external.created, post.external.updated, post.external.deleted, account.connected, account.disconnected, account.ads.initial_sync_completed, message.received, conversation.started, call.received, call.ended, call.failed, call.permission_request, message.sent, message.edited, message.deleted, message.delivered, message.read, message.failed, reaction.received, comment.received, review.new, review.updated, lead.received, ad.status_changed, whatsapp.template.status_updated, whatsapp.automatic_event, whatsapp.number.activated, whatsapp.number.declined, whatsapp.number.action_required, whatsapp.number.verification_required, whatsapp.number.suspended, whatsapp.number.reactivated, whatsapp.number.released, whatsapp.number.kyc_submitted, verification.approved, verification.failed]
|
|
24418
|
+
enum: [post.scheduled, post.published, post.failed, post.partial, post.cancelled, post.recycled, post.platform.published, post.platform.failed, post.platform.deleted, post.tiktok.url_resolved, post.external.created, post.external.updated, post.external.deleted, account.connected, account.disconnected, account.ads.initial_sync_completed, message.received, conversation.started, call.received, call.ended, call.failed, call.permission_request, message.sent, message.edited, message.deleted, message.delivered, message.read, message.failed, reaction.received, referral.received, comment.received, review.new, review.updated, lead.received, ad.status_changed, whatsapp.template.status_updated, whatsapp.template.category_updated, whatsapp.automatic_event, whatsapp.number.activated, whatsapp.number.declined, whatsapp.number.action_required, whatsapp.number.verification_required, whatsapp.number.suspended, whatsapp.number.reactivated, whatsapp.number.released, whatsapp.number.kyc_submitted, verification.approved, verification.failed]
|
|
23459
24419
|
description: Events to subscribe to. Must contain at least one event if provided.
|
|
23460
24420
|
isActive:
|
|
23461
24421
|
type: boolean
|
|
@@ -23985,13 +24945,15 @@ paths:
|
|
|
23985
24945
|
metadata:
|
|
23986
24946
|
type: [object, "null"]
|
|
23987
24947
|
description: |
|
|
23988
|
-
|
|
23989
|
-
Absent when the conversation did not
|
|
23990
|
-
|
|
23991
|
-
|
|
23992
|
-
|
|
23993
|
-
person later
|
|
23994
|
-
|
|
24948
|
+
Click attribution for a conversation that started from a Meta ad or
|
|
24949
|
+
a ref-tagged ig.me / m.me link. Absent when the conversation did not
|
|
24950
|
+
originate from an attributable click.
|
|
24951
|
+
|
|
24952
|
+
Captured from the referral Meta delivers for the click. If the same
|
|
24953
|
+
person later arrives through a different ad or link, the original
|
|
24954
|
+
values are kept, so the first referral wins; read the fresh referral
|
|
24955
|
+
per click on the `message.received` / `referral.received` webhooks
|
|
24956
|
+
instead. One exception on WhatsApp: when Meta omits `ctwa_clid`
|
|
23995
24957
|
from that referral, a later Meta automatic event can supply it and
|
|
23996
24958
|
refresh `ctwa_captured_at`, so treat `ctwa_captured_at` as the time
|
|
23997
24959
|
Zernio stored the value, not the time of the click.
|
|
@@ -24000,9 +24962,11 @@ paths:
|
|
|
24000
24962
|
|
|
24001
24963
|
- `ctwa_*` is WhatsApp Click-to-WhatsApp. The ad ID is
|
|
24002
24964
|
`ctwa_source_id`. There is no `meta_ad_id` on WhatsApp.
|
|
24003
|
-
- `meta_ad_*` is Instagram Click-to-Direct
|
|
24004
|
-
Click-to-Message. The ad ID is
|
|
24005
|
-
|
|
24965
|
+
- `meta_ad_*` is Instagram Click-to-Direct, Facebook Messenger
|
|
24966
|
+
Click-to-Message, and ig.me / m.me ref links. The ad ID is
|
|
24967
|
+
`meta_ad_id` (ad clicks only; a link capture carries
|
|
24968
|
+
`meta_ad_ref` without it). `ctwa_clid` never appears on these
|
|
24969
|
+
platforms.
|
|
24006
24970
|
|
|
24007
24971
|
Every key is optional and only the keys Meta supplied are returned, so
|
|
24008
24972
|
read defensively. Meta does not send a campaign or ad set ID, so none
|
|
@@ -24036,16 +25000,16 @@ paths:
|
|
|
24036
25000
|
description: "WhatsApp only. When Zernio stored this referral. Always present when a WhatsApp referral was captured."
|
|
24037
25001
|
meta_ad_id:
|
|
24038
25002
|
type: string
|
|
24039
|
-
description: "Instagram and Facebook only. The Meta ad ID the user clicked.
|
|
25003
|
+
description: "Instagram and Facebook only. The Meta ad ID the user clicked. Present for ad clicks; absent when the capture came from an ig.me / m.me ref link."
|
|
24040
25004
|
meta_ad_source:
|
|
24041
25005
|
type: string
|
|
24042
|
-
description: "Instagram and Facebook only. Meta-supplied source identifier, for
|
|
25006
|
+
description: "Instagram and Facebook only. Meta-supplied source identifier: ADS for ad clicks; SHORTLINK, SHORTLINKS or IGME-SOURCE-LINK for ref links (treat as opaque)."
|
|
24043
25007
|
meta_ad_type:
|
|
24044
25008
|
type: string
|
|
24045
25009
|
description: "Instagram and Facebook only. Meta-supplied referral type, for example OPEN_THREAD."
|
|
24046
25010
|
meta_ad_ref:
|
|
24047
25011
|
type: string
|
|
24048
|
-
description: "Instagram and Facebook only. The ref parameter passed through from the ad creative."
|
|
25012
|
+
description: "Instagram and Facebook only. The ref parameter passed through from the ad creative or the ig.me / m.me link."
|
|
24049
25013
|
meta_ad_title:
|
|
24050
25014
|
type: string
|
|
24051
25015
|
description: "Instagram and Facebook only. Title of the ad creative at click time."
|
|
@@ -24154,6 +25118,15 @@ paths:
|
|
|
24154
25118
|
already categorized at creation). Utility messages only; marketing
|
|
24155
25119
|
content is not allowed under this category. Accepted on the JSON
|
|
24156
25120
|
body only, not on multipart requests.
|
|
25121
|
+
linkPreview:
|
|
25122
|
+
type: boolean
|
|
25123
|
+
default: true
|
|
25124
|
+
description: >-
|
|
25125
|
+
WhatsApp only. Set false to send the Direct Send (category: 'utility')
|
|
25126
|
+
text message without a link-preview thumbnail for the first URL in the
|
|
25127
|
+
text. Defaults to true, which is how every WhatsApp text has been sent
|
|
25128
|
+
to date. Does not apply to template sends. Accepted on the JSON body
|
|
25129
|
+
only, not on multipart requests.
|
|
24157
25130
|
templateLanguage:
|
|
24158
25131
|
type: string
|
|
24159
25132
|
description: WhatsApp only. Template language code (e.g. en_US).
|
|
@@ -24316,7 +25289,7 @@ paths:
|
|
|
24316
25289
|
- name: cursor
|
|
24317
25290
|
in: query
|
|
24318
25291
|
schema: { type: string }
|
|
24319
|
-
description:
|
|
25292
|
+
description: "Opaque pagination cursor. Pass back pagination.nextCursor verbatim; do not construct one."
|
|
24320
25293
|
responses:
|
|
24321
25294
|
'200':
|
|
24322
25295
|
description: Conversations containing the query, most recent match first
|
|
@@ -24384,7 +25357,7 @@ paths:
|
|
|
24384
25357
|
accountId: { type: string }
|
|
24385
25358
|
platform: { type: string }
|
|
24386
25359
|
'400':
|
|
24387
|
-
description: Invalid query or
|
|
25360
|
+
description: 'Invalid query, unsupported platform, or malformed cursor'
|
|
24388
25361
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
24389
25362
|
'403':
|
|
24390
25363
|
description: Inbox addon required
|
|
@@ -24633,7 +25606,7 @@ paths:
|
|
|
24633
25606
|
in: query
|
|
24634
25607
|
required: false
|
|
24635
25608
|
schema: { type: string }
|
|
24636
|
-
description: Opaque pagination cursor. Pass `pagination.nextCursor` from a prior response.
|
|
25609
|
+
description: 'Opaque pagination cursor. Pass `pagination.nextCursor` from a prior response verbatim: a cursor we cannot parse returns 400 rather than silently restarting from the first page.'
|
|
24637
25610
|
- name: sortOrder
|
|
24638
25611
|
in: query
|
|
24639
25612
|
required: false
|
|
@@ -24772,6 +25745,7 @@ paths:
|
|
|
24772
25745
|
and for inbound interactive taps `interactiveType` / `interactiveId`.
|
|
24773
25746
|
additionalProperties: true
|
|
24774
25747
|
lastUpdated: { type: string, format: date-time }
|
|
25748
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
24775
25749
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
24776
25750
|
'403':
|
|
24777
25751
|
description: Inbox addon required
|
|
@@ -24822,7 +25796,7 @@ paths:
|
|
|
24822
25796
|
properties:
|
|
24823
25797
|
accountId: { type: string, description: Social account ID }
|
|
24824
25798
|
message: { type: string, description: Message text }
|
|
24825
|
-
attachmentUrl: { type: string, description: "URL of the attachment to send (image, video, audio, or file). The URL must be publicly accessible. For binary file uploads, use multipart/form-data instead." }
|
|
25799
|
+
attachmentUrl: { type: string, description: "URL of the attachment to send (image, video, audio, or file). The URL must be publicly accessible. For binary file uploads, use multipart/form-data instead. On WhatsApp, combining an image, video, or file with `buttons` renders the media as the header of one interactive reply-button message; audio cannot be combined with buttons." }
|
|
24826
25800
|
category:
|
|
24827
25801
|
type: string
|
|
24828
25802
|
enum: [utility]
|
|
@@ -24840,6 +25814,14 @@ paths:
|
|
|
24840
25814
|
Utility messages only; marketing content is not allowed under
|
|
24841
25815
|
this category. Accepted on the JSON body only, not on multipart
|
|
24842
25816
|
requests.
|
|
25817
|
+
linkPreview:
|
|
25818
|
+
type: boolean
|
|
25819
|
+
default: true
|
|
25820
|
+
description: >-
|
|
25821
|
+
WhatsApp only. Set false to send the message without a link-preview
|
|
25822
|
+
thumbnail for the first URL in the text. Defaults to true, which is how
|
|
25823
|
+
every WhatsApp text has been sent to date. Ignored on other platforms.
|
|
25824
|
+
Accepted on the JSON body only, not on multipart requests.
|
|
24843
25825
|
attachmentType:
|
|
24844
25826
|
type: string
|
|
24845
25827
|
enum: [image, video, audio, file]
|
|
@@ -24885,6 +25867,12 @@ paths:
|
|
|
24885
25867
|
reply-button message, provide `title` + `payload` and set
|
|
24886
25868
|
`type: postback`, e.g.
|
|
24887
25869
|
`{ "type": "postback", "title": "Yes", "payload": "yes" }`.
|
|
25870
|
+
|
|
25871
|
+
Combine `buttons` with `attachmentUrl` and `attachmentType`
|
|
25872
|
+
`image`, `video`, or `file` to render one WhatsApp message with
|
|
25873
|
+
a media header, body text, and reply buttons. Audio is not a
|
|
25874
|
+
supported interactive header and returns 400 when combined
|
|
25875
|
+
with buttons.
|
|
24888
25876
|
items:
|
|
24889
25877
|
type: object
|
|
24890
25878
|
required: [type, title]
|
|
@@ -25260,6 +26248,27 @@ paths:
|
|
|
25260
26248
|
properties:
|
|
25261
26249
|
email: { type: string }
|
|
25262
26250
|
type: { type: string }
|
|
26251
|
+
examples:
|
|
26252
|
+
whatsappImageWithReplyButtons:
|
|
26253
|
+
summary: WhatsApp image, body text, and reply buttons
|
|
26254
|
+
description: |
|
|
26255
|
+
The recipient sees one WhatsApp message containing the property
|
|
26256
|
+
image as its header, "Reply yes to continue." as the body, and
|
|
26257
|
+
two tappable reply buttons labelled Yes and No. A tap arrives on
|
|
26258
|
+
the `message.received` webhook as `metadata.interactiveType:
|
|
26259
|
+
button_reply`; `metadata.interactiveId` is `btn_0` or `btn_1`.
|
|
26260
|
+
value:
|
|
26261
|
+
accountId: 6a7adc04d0fe733d1a1bed76
|
|
26262
|
+
message: Reply yes to continue.
|
|
26263
|
+
attachmentUrl: https://cdn.example.com/property.jpg
|
|
26264
|
+
attachmentType: image
|
|
26265
|
+
buttons:
|
|
26266
|
+
- type: postback
|
|
26267
|
+
title: Yes
|
|
26268
|
+
payload: btn_0
|
|
26269
|
+
- type: postback
|
|
26270
|
+
title: No
|
|
26271
|
+
payload: btn_1
|
|
25263
26272
|
multipart/form-data:
|
|
25264
26273
|
schema:
|
|
25265
26274
|
type: object
|
|
@@ -25270,13 +26279,13 @@ paths:
|
|
|
25270
26279
|
attachment:
|
|
25271
26280
|
type: string
|
|
25272
26281
|
format: binary
|
|
25273
|
-
description: "File attachment (images, videos, documents). Supported formats: JPEG, PNG, GIF, MP4, AAC, WAV. Max 25MB."
|
|
26282
|
+
description: "File attachment (images, videos, documents). Supported formats: JPEG, PNG, GIF, MP4, AAC, WAV. Max 25MB. On WhatsApp, combining an image, video, or document upload with buttons renders the upload as the interactive message header; audio plus buttons is rejected."
|
|
25274
26283
|
quickReplies:
|
|
25275
26284
|
type: string
|
|
25276
26285
|
description: JSON string of quick replies array (same schema as application/json body)
|
|
25277
26286
|
buttons:
|
|
25278
26287
|
type: string
|
|
25279
|
-
description: JSON string of buttons array (same schema as application/json body)
|
|
26288
|
+
description: JSON string of buttons array (same schema as application/json body). On WhatsApp, an accompanying image, video, or document attachment becomes the interactive message header.
|
|
25280
26289
|
template:
|
|
25281
26290
|
type: string
|
|
25282
26291
|
description: JSON string of template object (same schema as application/json body)
|
|
@@ -26060,8 +27069,18 @@ paths:
|
|
|
26060
27069
|
(Instagram side); a row whose count can't be read is omitted.
|
|
26061
27070
|
|
|
26062
27071
|
Pagination walks each account's platform listing. Following `nextCursor` reaches past
|
|
26063
|
-
the first page on Facebook
|
|
26064
|
-
support a server-side date window; on the others the listing stops
|
|
27072
|
+
the first page on Facebook, Instagram, Threads, LinkedIn and YouTube, since they are
|
|
27073
|
+
the platforms that support a server-side date window; on the others the listing stops
|
|
27074
|
+
at its first page. Cursor pagination is only coherent for the default sort
|
|
27075
|
+
(`sortBy=date`, `sortOrder=desc`): with `sortOrder=asc`, or with `sortBy=comments`,
|
|
27076
|
+
the cursor filter does not match the sort order and the second page is unreliable.
|
|
27077
|
+
|
|
27078
|
+
`nextCursor` is opaque: pass it back verbatim, never construct or parse it, its
|
|
27079
|
+
composition may change without notice. Because each page re-queries a live window,
|
|
27080
|
+
results can still shift between requests, so dedupe by `id` on the client.
|
|
27081
|
+
|
|
27082
|
+
`commentCount` semantics differ by platform: YouTube's includes replies, Facebook's counts
|
|
27083
|
+
top-level comments only.
|
|
26065
27084
|
tags: [Comments]
|
|
26066
27085
|
security: [{ bearerAuth: [] }]
|
|
26067
27086
|
parameters:
|
|
@@ -26158,14 +27177,19 @@ paths:
|
|
|
26158
27177
|
x-resource-group: "engagement"
|
|
26159
27178
|
operationId: getInboxPostComments
|
|
26160
27179
|
summary: Get post comments
|
|
26161
|
-
description:
|
|
27180
|
+
description: |
|
|
27181
|
+
Fetch comments for a specific post. Requires accountId query parameter.
|
|
27182
|
+
|
|
27183
|
+
On Facebook and Instagram, passing a COMMENT id as `postId` is also supported and
|
|
27184
|
+
returns that comment's replies instead of the post's top-level comments. This is not
|
|
27185
|
+
available on YouTube, where `postId` must be a video id.
|
|
26162
27186
|
tags: [Comments]
|
|
26163
27187
|
security: [{ bearerAuth: [] }]
|
|
26164
27188
|
parameters:
|
|
26165
27189
|
- name: postId
|
|
26166
27190
|
in: path
|
|
26167
27191
|
required: true
|
|
26168
|
-
description: Zernio post ID or platform-specific post ID. Zernio IDs are auto-resolved. LinkedIn third-party posts accept full activity URN or numeric ID.
|
|
27192
|
+
description: Zernio post ID or platform-specific post ID. Zernio IDs are auto-resolved. LinkedIn third-party posts accept full activity URN or numeric ID. On Facebook and Instagram, a comment ID is also accepted here and returns that comment's replies.
|
|
26169
27193
|
schema: { type: string }
|
|
26170
27194
|
- name: accountId
|
|
26171
27195
|
in: query
|
|
@@ -26182,7 +27206,7 @@ paths:
|
|
|
26182
27206
|
- name: cursor
|
|
26183
27207
|
in: query
|
|
26184
27208
|
schema: { type: string }
|
|
26185
|
-
description: Pagination cursor
|
|
27209
|
+
description: 'Pagination cursor, returned by a previous call as `pagination.cursor`. This is the platform''s own opaque paging value passed through verbatim: never construct, decode or validate it client-side.'
|
|
26186
27210
|
- name: commentId
|
|
26187
27211
|
in: query
|
|
26188
27212
|
schema: { type: string }
|
|
@@ -26217,7 +27241,7 @@ paths:
|
|
|
26217
27241
|
enum: [blue, government, business, none]
|
|
26218
27242
|
description: X/Twitter verified badge type. Only present for Twitter/X comments.
|
|
26219
27243
|
likeCount: { type: integer }
|
|
26220
|
-
replyCount: { type: integer }
|
|
27244
|
+
replyCount: { type: integer, description: "The platform's own reply count, which includes hidden and deleted replies. Can exceed replies[].length even when repliesHasMore is false or absent." }
|
|
26221
27245
|
platform: { type: string, description: The platform this comment is from }
|
|
26222
27246
|
url:
|
|
26223
27247
|
type: [string, "null"]
|
|
@@ -26225,6 +27249,9 @@ paths:
|
|
|
26225
27249
|
replies:
|
|
26226
27250
|
type: array
|
|
26227
27251
|
items: { type: object }
|
|
27252
|
+
repliesHasMore:
|
|
27253
|
+
type: boolean
|
|
27254
|
+
description: "Facebook only. True when replies[] (capped at 10) does not hold the comment's full reply thread; fetch the rest by passing the comment id as postId to GET /v1/inbox/comments/{postId}. Absent (not false) on every other platform, including Instagram, which has no equivalent signal."
|
|
26228
27255
|
canReply: { type: boolean }
|
|
26229
27256
|
canDelete: { type: boolean }
|
|
26230
27257
|
canHide: { type: boolean, description: "Whether this comment can be hidden (Facebook, Instagram, Threads)" }
|
|
@@ -26233,7 +27260,7 @@ paths:
|
|
|
26233
27260
|
isLiked: { type: boolean, description: Whether the current user has liked this comment }
|
|
26234
27261
|
likeUri: { type: [string, "null"], description: Bluesky like URI for unliking }
|
|
26235
27262
|
cid: { type: [string, "null"], description: Bluesky content identifier }
|
|
26236
|
-
parentId: { type: [string, "null"], description:
|
|
27263
|
+
parentId: { type: [string, "null"], description: 'ID of the parent comment. Present on entries inside replies[] for Facebook, Instagram and X/Twitter. On X/Twitter it is also present on top-level entries, where it holds the ID of the post replied to. Omitted entirely (key absent, not null) on top-level Facebook and Instagram entries and on every other platform, which express the parent relationship only through replies[] nesting.' }
|
|
26237
27264
|
rootUri: { type: [string, "null"], description: Bluesky root post URI }
|
|
26238
27265
|
rootCid: { type: [string, "null"], description: Bluesky root post CID }
|
|
26239
27266
|
post:
|
|
@@ -26364,6 +27391,7 @@ paths:
|
|
|
26364
27391
|
- name: commentId
|
|
26365
27392
|
in: query
|
|
26366
27393
|
required: true
|
|
27394
|
+
description: 'For LinkedIn, accepts either the numeric comment ID or the composite comment URN returned by the comments listing (e.g. urn:li:comment:(threadUrn,id))'
|
|
26367
27395
|
schema: { type: string }
|
|
26368
27396
|
responses:
|
|
26369
27397
|
'200':
|
|
@@ -29007,6 +30035,15 @@ paths:
|
|
|
29007
30035
|
US numbers must have an approved carrier registration
|
|
29008
30036
|
(`/v1/sms/registrations`) before messages deliver.
|
|
29009
30037
|
|
|
30038
|
+
**Replies and delivery status arrive as webhooks**, not by polling:
|
|
30039
|
+
an inbound reply fires `message.received` with `platform: "sms"`, the
|
|
30040
|
+
first message of a new thread also fires `conversation.started`, and
|
|
30041
|
+
this message's own outcome fires `message.delivered` or
|
|
30042
|
+
`message.failed` (the latter carrying the carrier's error code).
|
|
30043
|
+
|
|
30044
|
+
**Opted-out recipients:** a send to a number that replied STOP is
|
|
30045
|
+
refused with `409`, never silently dropped.
|
|
30046
|
+
|
|
29010
30047
|
**Idempotency:** send an `Idempotency-Key` header to make retries safe:
|
|
29011
30048
|
same key + same body replays the original response instead of sending a
|
|
29012
30049
|
second message; same key + different body returns 422; a key still in
|
|
@@ -29046,9 +30083,10 @@ paths:
|
|
|
29046
30083
|
id: { type: string, description: Message ID }
|
|
29047
30084
|
conversationId: { type: string, description: Inbox conversation the message was threaded into. }
|
|
29048
30085
|
status: { type: string, enum: [sent] }
|
|
30086
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
29049
30087
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
29050
30088
|
'404': { description: "No SMS-enabled number matches `from`" }
|
|
29051
|
-
'409': {
|
|
30089
|
+
'409': { description: "Recipient has opted out (replied STOP), or the same Idempotency-Key is still in flight" }
|
|
29052
30090
|
'422': { $ref: '#/components/responses/IdempotencyKeyReused' }
|
|
29053
30091
|
'502': { description: Carrier-side send failed }
|
|
29054
30092
|
|
|
@@ -30573,6 +31611,47 @@ paths:
|
|
|
30573
31611
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
30574
31612
|
'404': { description: WhatsApp account not found }
|
|
30575
31613
|
|
|
31614
|
+
/v1/whatsapp/account-events:
|
|
31615
|
+
get:
|
|
31616
|
+
x-resource-group: "accounts"
|
|
31617
|
+
operationId: listWhatsAppAccountEvents
|
|
31618
|
+
tags: [WhatsApp]
|
|
31619
|
+
summary: List account notifications
|
|
31620
|
+
description: |
|
|
31621
|
+
Returns Meta-originated events recorded for a WhatsApp account, newest
|
|
31622
|
+
first: template review outcomes (approved, rejected, paused, category
|
|
31623
|
+
changes) and WABA status changes (restricted, disabled, reinstated,
|
|
31624
|
+
disconnected). Events are captured from Meta webhooks as they happen;
|
|
31625
|
+
the feed starts at the account's first recorded event and is not
|
|
31626
|
+
backfilled. Complements the push events `whatsapp.template.status_updated`
|
|
31627
|
+
and `account.disconnected` with a pollable history.
|
|
31628
|
+
security:
|
|
31629
|
+
- bearerAuth: []
|
|
31630
|
+
parameters:
|
|
31631
|
+
- { name: accountId, in: query, required: true, schema: { type: string }, description: WhatsApp social account ID }
|
|
31632
|
+
- { name: limit, in: query, required: false, schema: { type: integer, minimum: 1, maximum: 200, default: 50 }, description: Maximum events to return }
|
|
31633
|
+
responses:
|
|
31634
|
+
'200':
|
|
31635
|
+
description: Recorded events, newest first
|
|
31636
|
+
content:
|
|
31637
|
+
application/json:
|
|
31638
|
+
schema:
|
|
31639
|
+
type: object
|
|
31640
|
+
properties:
|
|
31641
|
+
events:
|
|
31642
|
+
type: array
|
|
31643
|
+
items:
|
|
31644
|
+
type: object
|
|
31645
|
+
properties:
|
|
31646
|
+
id: { type: string }
|
|
31647
|
+
type: { type: string, description: 'Event kind, e.g. template_approved, template_rejected, account_restricted, account_disconnected' }
|
|
31648
|
+
severity: { type: string, enum: [info, success, warning, critical] }
|
|
31649
|
+
title: { type: string }
|
|
31650
|
+
detail: { type: [string, "null"] }
|
|
31651
|
+
createdAt: { type: string, format: date-time }
|
|
31652
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
31653
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
31654
|
+
'404': { description: WhatsApp account not found }
|
|
30576
31655
|
/v1/whatsapp/dataset:
|
|
30577
31656
|
get:
|
|
30578
31657
|
x-resource-group: "accounts"
|
|
@@ -30728,6 +31807,7 @@ paths:
|
|
|
30728
31807
|
endUserFirstName: { type: [string, "null"] }
|
|
30729
31808
|
endUserLastName: { type: [string, "null"] }
|
|
30730
31809
|
regulatoryDeclineReason: { type: [string, "null"], description: Reviewer rejection reason when status is regulatory_declined. }
|
|
31810
|
+
callingEnabled: { type: boolean, description: 'Whether WhatsApp Business Calling is enabled on this number (manage via /v1/whatsapp/phone-numbers/{id}/calling).' }
|
|
30731
31811
|
createdAt: { type: string, format: date-time }
|
|
30732
31812
|
connected:
|
|
30733
31813
|
type: array
|
|
@@ -30745,6 +31825,7 @@ paths:
|
|
|
30745
31825
|
displayName: { type: [string, "null"] }
|
|
30746
31826
|
profileId: { type: [string, "null"] }
|
|
30747
31827
|
connectedAt: { type: [string, "null"], format: date-time }
|
|
31828
|
+
callingEnabled: { type: boolean, description: 'Whether WhatsApp Business Calling is enabled on this number.' }
|
|
30748
31829
|
sandbox:
|
|
30749
31830
|
type: [object, "null"]
|
|
30750
31831
|
description: |
|
|
@@ -31267,6 +32348,7 @@ paths:
|
|
|
31267
32348
|
endUserFirstName: { type: [string, "null"] }
|
|
31268
32349
|
endUserLastName: { type: [string, "null"] }
|
|
31269
32350
|
regulatoryDeclineReason: { type: [string, "null"], description: Reviewer rejection reason when status is regulatory_declined. }
|
|
32351
|
+
callingEnabled: { type: boolean, description: 'Whether WhatsApp Business Calling is enabled on this number (manage via /v1/whatsapp/phone-numbers/{id}/calling).' }
|
|
31270
32352
|
createdAt: { type: string, format: date-time }
|
|
31271
32353
|
connected:
|
|
31272
32354
|
type: array
|
|
@@ -31284,6 +32366,7 @@ paths:
|
|
|
31284
32366
|
displayName: { type: [string, "null"] }
|
|
31285
32367
|
profileId: { type: [string, "null"] }
|
|
31286
32368
|
connectedAt: { type: [string, "null"], format: date-time }
|
|
32369
|
+
callingEnabled: { type: boolean, description: 'Whether WhatsApp Business Calling is enabled on this number.' }
|
|
31287
32370
|
sandbox:
|
|
31288
32371
|
type: [object, "null"]
|
|
31289
32372
|
description: |
|
|
@@ -31643,6 +32726,7 @@ paths:
|
|
|
31643
32726
|
label: { type: string }
|
|
31644
32727
|
value: { type: string }
|
|
31645
32728
|
documentId: { type: string, description: 'Present on document rows — the Telnyx document id. GET /v1/whatsapp/phone-numbers/kyc/document/{documentId} streams it (auth-scoped, inline PDF).' }
|
|
32729
|
+
pendingReview: { type: boolean, description: 'true when this account already has a number for this country in regulatory review (status pending_regulatory). Scope is the whole account across all profiles, and the country only (any number type), so it is not a per-end-client signal on a multi-tenant setup. Informational only: it never blocks a submission, and several same-country numbers may sit in review at once. For a per-end-client view, call GET /v1/phone-numbers with `profileId` and `status=pending_regulatory`; that view also lists numbers declined in the last 30 days.' }
|
|
31646
32730
|
'400': { description: Country not available }
|
|
31647
32731
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
31648
32732
|
post:
|
|
@@ -31680,7 +32764,7 @@ paths:
|
|
|
31680
32764
|
properties:
|
|
31681
32765
|
profileId: { type: string }
|
|
31682
32766
|
country: { type: string }
|
|
31683
|
-
submissionId: { type: string, description: Idempotency token for this submission attempt.
|
|
32767
|
+
submissionId: { type: string, description: 'Idempotency token for this submission attempt. Once the number has been ordered, a retry with the same token returns that same number instead of ordering another. A submission that fails before the number is ordered releases the token, so you can correct your details and re-submit with it. Omit it and every call provisions a new number.' }
|
|
31684
32768
|
quantity: { type: integer, minimum: 1, maximum: 5, default: 1, description: 'Provision several same-country numbers from one submission (1-5). The single verification covers all of them; each number is billed only when it activates. Numbers that fail to order are skipped (best-effort). With `areaCode`, a quantity above that area''s live stock is rejected with a 400.' }
|
|
31685
32769
|
reuse: { type: boolean, description: Reuse a prior approved verification for this country (skips document/field collection; places the order immediately). }
|
|
31686
32770
|
reuseOptionId: { type: string, description: 'Which reusable verification to use (GET reusable.options[].id). The unambiguous selection key. Omitted = the approved default. No match = 409.' }
|
|
@@ -31717,6 +32801,7 @@ paths:
|
|
|
31717
32801
|
first_name: { type: string }
|
|
31718
32802
|
last_name: { type: string }
|
|
31719
32803
|
street_address: { type: string }
|
|
32804
|
+
extended_address: { type: string, description: 'Address complement: apartment, suite, unit, or the quadra/lote used in some countries. Optional. Does not substitute for a building number on street_address.' }
|
|
31720
32805
|
locality: { type: string }
|
|
31721
32806
|
administrative_area: { type: string }
|
|
31722
32807
|
postal_code: { type: string }
|
|
@@ -31841,6 +32926,7 @@ paths:
|
|
|
31841
32926
|
properties:
|
|
31842
32927
|
country: { type: string, minLength: 2, maxLength: 2, description: ISO 3166-1 alpha-2 country code. }
|
|
31843
32928
|
street_address: { type: string }
|
|
32929
|
+
extended_address: { type: string, description: 'Address complement: apartment, suite, unit, or the quadra/lote used in some countries. Optional. Does not substitute for a building number on street_address.' }
|
|
31844
32930
|
locality: { type: string, description: City / town. }
|
|
31845
32931
|
administrative_area: { type: string, description: "State / province / region. When omitted, the pre-check is skipped (the final submit still validates)." }
|
|
31846
32932
|
postal_code: { type: string }
|
|
@@ -32629,6 +33715,7 @@ paths:
|
|
|
32629
33715
|
label: { type: string }
|
|
32630
33716
|
value: { type: string }
|
|
32631
33717
|
documentId: { type: string, description: 'Present on document rows — the Telnyx document id. GET /v1/whatsapp/phone-numbers/kyc/document/{documentId} streams it (auth-scoped, inline PDF).' }
|
|
33718
|
+
pendingReview: { type: boolean, description: 'true when this account already has a number for this country in regulatory review (status pending_regulatory). Scope is the whole account across all profiles, and the country only (any number type), so it is not a per-end-client signal on a multi-tenant setup. Informational only: it never blocks a submission, and several same-country numbers may sit in review at once. For a per-end-client view, call GET /v1/phone-numbers with `profileId` and `status=pending_regulatory`; that view also lists numbers declined in the last 30 days.' }
|
|
32632
33719
|
'400': { description: Country not available }
|
|
32633
33720
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
32634
33721
|
post:
|
|
@@ -32670,7 +33757,7 @@ paths:
|
|
|
32670
33757
|
properties:
|
|
32671
33758
|
profileId: { type: string }
|
|
32672
33759
|
country: { type: string }
|
|
32673
|
-
submissionId: { type: string, description: Idempotency token for this submission attempt.
|
|
33760
|
+
submissionId: { type: string, description: 'Idempotency token for this submission attempt. Once the number has been ordered, a retry with the same token returns that same number instead of ordering another. A submission that fails before the number is ordered releases the token, so you can correct your details and re-submit with it. Omit it and every call provisions a new number.' }
|
|
32674
33761
|
quantity: { type: integer, minimum: 1, maximum: 5, default: 1, description: 'Provision several same-country numbers from one submission (1-5). The single verification covers all of them; each number is billed only when it activates. Numbers that fail to order are skipped (best-effort). With `areaCode`, a quantity above that area''s live stock is rejected with a 400.' }
|
|
32675
33762
|
reuse: { type: boolean, description: Reuse a prior approved verification for this country (skips document/field collection; places the order immediately). }
|
|
32676
33763
|
reuseOptionId: { type: string, description: 'Which reusable verification to use (GET reusable.options[].id). The unambiguous selection key. Omitted = the approved default. No match = 409.' }
|
|
@@ -32707,6 +33794,7 @@ paths:
|
|
|
32707
33794
|
first_name: { type: string }
|
|
32708
33795
|
last_name: { type: string }
|
|
32709
33796
|
street_address: { type: string }
|
|
33797
|
+
extended_address: { type: string, description: 'Address complement: apartment, suite, unit, or the quadra/lote used in some countries. Optional. Does not substitute for a building number on street_address.' }
|
|
32710
33798
|
locality: { type: string }
|
|
32711
33799
|
administrative_area: { type: string }
|
|
32712
33800
|
postal_code: { type: string }
|
|
@@ -32810,6 +33898,7 @@ paths:
|
|
|
32810
33898
|
properties:
|
|
32811
33899
|
country: { type: string, minLength: 2, maxLength: 2, description: ISO 3166-1 alpha-2 country code. }
|
|
32812
33900
|
street_address: { type: string }
|
|
33901
|
+
extended_address: { type: string, description: 'Address complement: apartment, suite, unit, or the quadra/lote used in some countries. Optional. Does not substitute for a building number on street_address.' }
|
|
32813
33902
|
locality: { type: string, description: City / town. }
|
|
32814
33903
|
administrative_area: { type: string, description: "State / province / region. When omitted, the pre-check is skipped (the final submit still validates)." }
|
|
32815
33904
|
postal_code: { type: string }
|
|
@@ -35588,7 +36677,7 @@ paths:
|
|
|
35588
36677
|
contactId: { type: string }
|
|
35589
36678
|
channelId: { type: string }
|
|
35590
36679
|
platformIdentifier: { type: string }
|
|
35591
|
-
contactName: { type: string }
|
|
36680
|
+
contactName: { type: [string, "null"] }
|
|
35592
36681
|
status: { type: string, enum: [pending, sent, delivered, read, failed] }
|
|
35593
36682
|
messageId: { type: string }
|
|
35594
36683
|
error: { type: string }
|
|
@@ -35623,7 +36712,7 @@ paths:
|
|
|
35623
36712
|
schema:
|
|
35624
36713
|
type: object
|
|
35625
36714
|
properties:
|
|
35626
|
-
contactIds: { type: array, items: { type: string }, description: Specific contact IDs to add }
|
|
36715
|
+
contactIds: { type: array, items: { type: string }, description: 'Specific contact IDs to add. Zernio contact ids (24-character hex), as returned by the list-contacts endpoint. A platform identifier such as a WhatsApp wa_id is rejected with 400; use phones for raw numbers.' }
|
|
35627
36716
|
phones: { type: array, items: { type: string }, maxItems: 20000, description: Raw phone numbers (auto-creates contacts). Useful for WhatsApp/Telegram manual entry }
|
|
35628
36717
|
useSegment: { type: boolean, description: Auto-populate from broadcast segment filters }
|
|
35629
36718
|
responses:
|
|
@@ -36572,10 +37661,10 @@ paths:
|
|
|
36572
37661
|
contactName: { type: string }
|
|
36573
37662
|
currentStepIndex: { type: integer }
|
|
36574
37663
|
status: { type: string, enum: [active, completed, exited, paused] }
|
|
36575
|
-
exitReason: { type: string }
|
|
36576
|
-
nextStepAt: { type: string, format: date-time }
|
|
37664
|
+
exitReason: { type: [string, "null"] }
|
|
37665
|
+
nextStepAt: { type: [string, "null"], format: date-time }
|
|
36577
37666
|
stepsSent: { type: integer }
|
|
36578
|
-
lastStepSentAt: { type: string, format: date-time }
|
|
37667
|
+
lastStepSentAt: { type: [string, "null"], format: date-time }
|
|
36579
37668
|
createdAt: { type: string, format: date-time }
|
|
36580
37669
|
pagination:
|
|
36581
37670
|
type: object
|
|
@@ -37104,7 +38193,7 @@ paths:
|
|
|
37104
38193
|
- type: object
|
|
37105
38194
|
required: [backfillPending]
|
|
37106
38195
|
properties:
|
|
37107
|
-
backfillPending: { type: boolean,
|
|
38196
|
+
backfillPending: { type: boolean, description: 'Always true on this response. Part of the requested range is still being backfilled; retry until the request returns 200.' }
|
|
37108
38197
|
'400': { $ref: '#/components/responses/BadRequest' }
|
|
37109
38198
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
37110
38199
|
'403':
|
|
@@ -37168,6 +38257,130 @@ paths:
|
|
|
37168
38257
|
'429': { description: "Google Ads operations budget exhausted; retry later." }
|
|
37169
38258
|
'501': { description: Only available on Google Ads accounts }
|
|
37170
38259
|
|
|
38260
|
+
/v1/ads/local-services/leads:
|
|
38261
|
+
get:
|
|
38262
|
+
x-resource-group: "ads"
|
|
38263
|
+
operationId: listLocalServicesLeads
|
|
38264
|
+
tags: ["Ad Insights"]
|
|
38265
|
+
x-platforms: ["google"]
|
|
38266
|
+
summary: Google Local Services Ads leads
|
|
38267
|
+
description: |-
|
|
38268
|
+
Leads generated by Local Services Ads (phone calls, messages, bookings),
|
|
38269
|
+
read live from Google's `local_services_lead` resource, newest first.
|
|
38270
|
+
No persistence: Google is the source of truth and lead/credit statuses
|
|
38271
|
+
keep changing server-side. Google never returns healthcare-category
|
|
38272
|
+
leads, and `WIPED_OUT` leads arrive with contact erased (`contact` is
|
|
38273
|
+
null). Draws on the shared Google Ads operations budget.
|
|
38274
|
+
security:
|
|
38275
|
+
- bearerAuth: []
|
|
38276
|
+
parameters:
|
|
38277
|
+
- { name: accountId, in: query, required: true, schema: { type: string }, description: "Google ads SocialAccount id." }
|
|
38278
|
+
- { name: customerId, in: query, schema: { type: string }, description: "Numeric Google Ads customer id (no dashes). Defaults to the account's connected customer." }
|
|
38279
|
+
- { name: fromDate, in: query, schema: { type: string, format: date }, description: "Leads created at/after this day." }
|
|
38280
|
+
- { name: toDate, in: query, schema: { type: string, format: date }, description: "Leads created at/before this day." }
|
|
38281
|
+
- { name: leadType, in: query, schema: { type: string, enum: [PHONE_CALL, MESSAGE, BOOKING] } }
|
|
38282
|
+
- { name: leadStatus, in: query, schema: { type: string }, description: "Google LocalServicesLeadStatus enum value (e.g. NEW, BOOKED, WIPED_OUT)." }
|
|
38283
|
+
- { name: chargedOnly, in: query, schema: { type: boolean }, description: "true = only leads Google charged for." }
|
|
38284
|
+
- { name: pageToken, in: query, schema: { type: string }, description: "Cursor from paging.nextPageToken of the previous page." }
|
|
38285
|
+
responses:
|
|
38286
|
+
'200':
|
|
38287
|
+
description: Local Services leads
|
|
38288
|
+
content:
|
|
38289
|
+
application/json:
|
|
38290
|
+
schema:
|
|
38291
|
+
type: object
|
|
38292
|
+
properties:
|
|
38293
|
+
customerId: { type: string }
|
|
38294
|
+
data:
|
|
38295
|
+
type: array
|
|
38296
|
+
items:
|
|
38297
|
+
type: object
|
|
38298
|
+
properties:
|
|
38299
|
+
id: { type: [string, "null"], description: "Lead id; pass to /v1/ads/local-services/leads/{leadId}/conversations." }
|
|
38300
|
+
leadType: { type: [string, "null"], description: "PHONE_CALL / MESSAGE / BOOKING." }
|
|
38301
|
+
categoryId: { type: [string, "null"] }
|
|
38302
|
+
serviceId: { type: [string, "null"] }
|
|
38303
|
+
contact:
|
|
38304
|
+
type: [object, "null"]
|
|
38305
|
+
description: "Null for WIPED_OUT leads (contact erased by Google)."
|
|
38306
|
+
properties:
|
|
38307
|
+
consumerName: { type: [string, "null"] }
|
|
38308
|
+
email: { type: [string, "null"] }
|
|
38309
|
+
phoneNumber: { type: [string, "null"] }
|
|
38310
|
+
status: { type: [string, "null"] }
|
|
38311
|
+
createdTime: { type: [string, "null"], description: "Google datetime in the customer's timezone (YYYY-MM-DD HH:MM:SS)." }
|
|
38312
|
+
locale: { type: [string, "null"] }
|
|
38313
|
+
charged: { type: boolean }
|
|
38314
|
+
creditState: { type: [string, "null"] }
|
|
38315
|
+
creditStateLastUpdate: { type: [string, "null"] }
|
|
38316
|
+
paging:
|
|
38317
|
+
type: object
|
|
38318
|
+
properties:
|
|
38319
|
+
nextPageToken: { type: [string, "null"], description: "Null when the last page was returned." }
|
|
38320
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
38321
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
38322
|
+
'429': { description: "Google Ads operations budget exhausted; retry later." }
|
|
38323
|
+
'501': { description: Only available on Google Ads accounts }
|
|
38324
|
+
|
|
38325
|
+
/v1/ads/local-services/leads/{leadId}/conversations:
|
|
38326
|
+
get:
|
|
38327
|
+
x-resource-group: "ads"
|
|
38328
|
+
operationId: listLocalServicesLeadConversations
|
|
38329
|
+
tags: ["Ad Insights"]
|
|
38330
|
+
x-platforms: ["google"]
|
|
38331
|
+
summary: Conversations of a Local Services lead
|
|
38332
|
+
description: |-
|
|
38333
|
+
Conversation entries of one Local Services lead: phone calls (duration,
|
|
38334
|
+
recording URL) and messages (text, attachment URLs), oldest first. Read
|
|
38335
|
+
live from `local_services_lead_conversation`, always scoped to a single
|
|
38336
|
+
lead. Call-recording URLs require read access on the Google Ads account.
|
|
38337
|
+
Draws on the shared Google Ads operations budget.
|
|
38338
|
+
security:
|
|
38339
|
+
- bearerAuth: []
|
|
38340
|
+
parameters:
|
|
38341
|
+
- { name: leadId, in: path, required: true, schema: { type: string }, description: "Numeric lead id from /v1/ads/local-services/leads." }
|
|
38342
|
+
- { name: accountId, in: query, required: true, schema: { type: string }, description: "Google ads SocialAccount id." }
|
|
38343
|
+
- { name: customerId, in: query, schema: { type: string }, description: "Numeric Google Ads customer id (no dashes). Defaults to the account's connected customer." }
|
|
38344
|
+
- { name: pageToken, in: query, schema: { type: string }, description: "Cursor from paging.nextPageToken of the previous page." }
|
|
38345
|
+
responses:
|
|
38346
|
+
'200':
|
|
38347
|
+
description: Lead conversations
|
|
38348
|
+
content:
|
|
38349
|
+
application/json:
|
|
38350
|
+
schema:
|
|
38351
|
+
type: object
|
|
38352
|
+
properties:
|
|
38353
|
+
customerId: { type: string }
|
|
38354
|
+
data:
|
|
38355
|
+
type: array
|
|
38356
|
+
items:
|
|
38357
|
+
type: object
|
|
38358
|
+
properties:
|
|
38359
|
+
id: { type: [string, "null"] }
|
|
38360
|
+
channel: { type: [string, "null"], description: "PHONE_CALL / MESSAGE / SMS / EMAIL / WHATSAPP / ADS_API." }
|
|
38361
|
+
participantType: { type: [string, "null"], description: "ADVERTISER or CONSUMER." }
|
|
38362
|
+
eventDateTime: { type: [string, "null"] }
|
|
38363
|
+
phoneCall:
|
|
38364
|
+
type: [object, "null"]
|
|
38365
|
+
description: "Only on PHONE_CALL entries."
|
|
38366
|
+
properties:
|
|
38367
|
+
callDurationMillis: { type: [integer, "null"] }
|
|
38368
|
+
callRecordingUrl: { type: [string, "null"] }
|
|
38369
|
+
message:
|
|
38370
|
+
type: [object, "null"]
|
|
38371
|
+
description: "Only on message-channel entries."
|
|
38372
|
+
properties:
|
|
38373
|
+
text: { type: [string, "null"] }
|
|
38374
|
+
attachmentUrls: { type: array, items: { type: string } }
|
|
38375
|
+
paging:
|
|
38376
|
+
type: object
|
|
38377
|
+
properties:
|
|
38378
|
+
nextPageToken: { type: [string, "null"], description: "Null when the last page was returned." }
|
|
38379
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
38380
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
38381
|
+
'429': { description: "Google Ads operations budget exhausted; retry later." }
|
|
38382
|
+
'501': { description: Only available on Google Ads accounts }
|
|
38383
|
+
|
|
37171
38384
|
/v1/ads/keywords:
|
|
37172
38385
|
get:
|
|
37173
38386
|
x-resource-group: "ads"
|
|
@@ -37272,6 +38485,8 @@ paths:
|
|
|
37272
38485
|
- { name: profileId, in: query, schema: { type: string }, description: Profile ID }
|
|
37273
38486
|
- { name: fromDate, in: query, schema: { type: string, format: date }, description: "Start of metrics date range (YYYY-MM-DD, inclusive). Defaults to 90 days ago when both date params are omitted." }
|
|
37274
38487
|
- { name: toDate, in: query, schema: { type: string, format: date }, description: "End of metrics date range (YYYY-MM-DD, inclusive). Defaults to today. Max 730-day range." }
|
|
38488
|
+
- { name: hasDelivery, in: query, schema: { type: boolean }, description: "Return only campaigns that delivered between `fromDate` and `toDate` — spend above zero, or impressions served at zero spend. Unlike `status`, which reads a campaign's CURRENT state, this filters on what happened inside the window. Filters the campaign set itself, so `pagination.total` counts only matching campaigns. Mirrors the same filter on /v1/ads/tree." }
|
|
38489
|
+
- { name: minSpend, in: query, schema: { type: number, minimum: 0 }, description: "Return only campaigns whose spend between `fromDate` and `toDate` reaches this amount, in each campaign's OWN currency (the `currency` field on the campaign). Implies `hasDelivery`; `minSpend=0` applies no filter. Mirrors the same filter on /v1/ads/tree." }
|
|
37275
38490
|
responses:
|
|
37276
38491
|
'200':
|
|
37277
38492
|
description: Paginated campaigns
|
|
@@ -37367,8 +38582,20 @@ paths:
|
|
|
37367
38582
|
x-platforms: ["meta", "google", "tiktok", "linkedin", "pinterest", "x", "openai"]
|
|
37368
38583
|
summary: Pause or resume a campaign
|
|
37369
38584
|
description: |
|
|
37370
|
-
|
|
37371
|
-
|
|
38585
|
+
Writes the campaign's own on/off switch, then lets the platform cascade delivery to its ad sets and ads.
|
|
38586
|
+
Makes one platform API call, not one per ad.
|
|
38587
|
+
|
|
38588
|
+
The switch is always written, whatever delivery status the ads underneath report: an ad still in review
|
|
38589
|
+
does not block resuming its campaign. The echoed `status` is the confirmation that it landed.
|
|
38590
|
+
|
|
38591
|
+
`updated` / `skipped` describe only the ads whose own stored status CHANGED alongside it, so
|
|
38592
|
+
`updated: 0` is a normal successful response, not a no-op. Ads are skipped when they are in a terminal
|
|
38593
|
+
status (rejected, completed, cancelled), already in the target state, or switched on but not yet
|
|
38594
|
+
delivering — the last group keeps its `pending_review` / `error` status until the platform reports what
|
|
38595
|
+
it became. `skippedReasons` names which case applies.
|
|
38596
|
+
|
|
38597
|
+
On Meta this flips the campaign only. An ad set paused in its own right stays paused, so pair this with
|
|
38598
|
+
PUT /v1/ads/ad-sets/{adSetId}/status when you also need the ad set switched back on.
|
|
37372
38599
|
security:
|
|
37373
38600
|
- bearerAuth: []
|
|
37374
38601
|
parameters:
|
|
@@ -37391,10 +38618,10 @@ paths:
|
|
|
37391
38618
|
schema:
|
|
37392
38619
|
type: object
|
|
37393
38620
|
properties:
|
|
37394
|
-
|
|
37395
|
-
|
|
37396
|
-
|
|
37397
|
-
|
|
38621
|
+
status: { type: string, enum: [active, paused], description: The status written to the campaign }
|
|
38622
|
+
updated: { type: integer, description: 'Number of ads whose own stored status changed too. 0 is normal on a resume whose ads are all awaiting the platform.' }
|
|
38623
|
+
skipped: { type: integer, description: 'Number of ads whose own status was left as it was' }
|
|
38624
|
+
skippedReasons: { type: array, items: { type: string }, description: 'Why each group of ads was skipped' }
|
|
37398
38625
|
'400':
|
|
37399
38626
|
description: Invalid input or campaign spans multiple social accounts
|
|
37400
38627
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
@@ -37897,7 +39124,7 @@ paths:
|
|
|
37897
39124
|
properties:
|
|
37898
39125
|
amount: { type: number }
|
|
37899
39126
|
type: { type: string, enum: [daily, lifetime] }
|
|
37900
|
-
status: { type: string, enum: [active, paused], description: Omit if not toggling delivery state }
|
|
39127
|
+
status: { type: string, enum: [active, paused], description: "Writes the ad set's own on/off switch (Meta: `configured_status`) on Meta and LinkedIn, whatever delivery status its ads report. Omit if not toggling delivery state." }
|
|
37901
39128
|
name: { type: string, maxLength: 255, description: "Rename the ad set (Meta only; other platforms return 501). At least one of budget/status/bidStrategy/name is required." }
|
|
37902
39129
|
bidStrategy:
|
|
37903
39130
|
allOf: [{ $ref: '#/components/schemas/BidStrategy' }]
|
|
@@ -37976,9 +39203,11 @@ paths:
|
|
|
37976
39203
|
properties:
|
|
37977
39204
|
budget: { $ref: '#/components/schemas/AdBudget' }
|
|
37978
39205
|
budgetLevel: { type: string, enum: [adset] }
|
|
37979
|
-
status: { type: string, enum: [active, paused] }
|
|
37980
|
-
statusUpdated: { type: integer }
|
|
37981
|
-
statusSkipped: { type: integer }
|
|
39206
|
+
status: { type: string, enum: [active, paused], description: 'The status written to the ad set. Absent when nothing was written (see statusMessage).' }
|
|
39207
|
+
statusUpdated: { type: integer, description: 'Number of ads whose own stored status changed alongside the ad set switch' }
|
|
39208
|
+
statusSkipped: { type: integer, description: 'Number of ads whose own status was left as it was' }
|
|
39209
|
+
statusSkippedReasons: { type: array, items: { type: string }, description: 'Why each group of ads was skipped' }
|
|
39210
|
+
statusMessage: { type: string, description: 'Present only where the platform has no ad-set switch and no child ad was actionable; `status` is then absent because nothing was written' }
|
|
37982
39211
|
bidStrategy: { $ref: '#/components/schemas/BidStrategy' }
|
|
37983
39212
|
bidAmount: { type: [number, "null"] }
|
|
37984
39213
|
roasAverageFloor: { type: [number, "null"] }
|
|
@@ -38002,6 +39231,23 @@ paths:
|
|
|
38002
39231
|
over PUT /v1/ads/ad-sets/{adSetId} for callers that only want the
|
|
38003
39232
|
status toggle and prefer a symmetric URL to
|
|
38004
39233
|
/v1/ads/campaigns/{campaignId}/status.
|
|
39234
|
+
|
|
39235
|
+
On Meta and LinkedIn this writes the ad set's own on/off switch
|
|
39236
|
+
(Meta: `configured_status`), whatever delivery status its ads report —
|
|
39237
|
+
an ad still in review does not block resuming its ad set. The echoed
|
|
39238
|
+
`status` is the confirmation that it landed. Where the platform has no
|
|
39239
|
+
ad-set switch (TikTok and others) the toggle is emulated by flipping the
|
|
39240
|
+
child ads; a call with no actionable ad then writes nothing and returns a
|
|
39241
|
+
`message` with no `status`.
|
|
39242
|
+
|
|
39243
|
+
`updated` / `skipped` describe only the ads whose own stored status
|
|
39244
|
+
CHANGED alongside the switch, so `updated: 0` is a normal successful
|
|
39245
|
+
response. See `skippedReasons` for which of the three cases applies
|
|
39246
|
+
(terminal, already in the target state, or switched on but not yet
|
|
39247
|
+
delivering).
|
|
39248
|
+
|
|
39249
|
+
A campaign created paused needs its campaign resumed as well: pair this
|
|
39250
|
+
with PUT /v1/ads/campaigns/{campaignId}/status.
|
|
38005
39251
|
security:
|
|
38006
39252
|
- bearerAuth: []
|
|
38007
39253
|
parameters:
|
|
@@ -38024,8 +39270,11 @@ paths:
|
|
|
38024
39270
|
schema:
|
|
38025
39271
|
type: object
|
|
38026
39272
|
properties:
|
|
38027
|
-
|
|
38028
|
-
|
|
39273
|
+
status: { type: string, enum: [active, paused], description: 'The status written to the ad set. Absent when nothing was written (see message).' }
|
|
39274
|
+
updated: { type: integer, description: 'Number of ads whose own stored status changed too. 0 is normal on a resume whose ads are all awaiting the platform.' }
|
|
39275
|
+
skipped: { type: integer, description: 'Number of ads whose own status was left as it was' }
|
|
39276
|
+
skippedReasons: { type: array, items: { type: string }, description: 'Why each group of ads was skipped' }
|
|
39277
|
+
message: { type: string, description: 'Present only where the platform has no ad-set switch and no child ad was actionable' }
|
|
38029
39278
|
'400': { description: Invalid input }
|
|
38030
39279
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
38031
39280
|
'404': { description: Ad set not found }
|
|
@@ -38068,8 +39317,10 @@ paths:
|
|
|
38068
39317
|
- { name: accountId, in: query, schema: { type: string }, description: Social account ID }
|
|
38069
39318
|
- { name: profileId, in: query, schema: { type: string }, description: Profile ID }
|
|
38070
39319
|
- { name: campaignId, in: query, schema: { type: string }, description: "Restrict the tree to a single campaign by its platform campaign id (the id the platform assigns, e.g. Meta's numeric campaign id). Filters the campaign set itself, so it works regardless of account size and pagination — pass this when you already hold a campaign id instead of paging the tree to find it. Mirrors the `campaignId` filter on GET /v1/ads." }
|
|
38071
|
-
- { name: fromDate, in: query, schema: { type: string, format: date }, description: "Start of the METRICS date range (YYYY-MM-DD).
|
|
39320
|
+
- { name: fromDate, in: query, schema: { type: string, format: date }, description: "Start of the METRICS date range (YYYY-MM-DD). On its own it affects only the spend/impression numbers overlaid on each node, not which campaigns are returned — pass `hasDelivery` or `minSpend` to also filter the campaign set to this window. Defaults to 90 days ago." }
|
|
38072
39321
|
- { name: toDate, in: query, schema: { type: string, format: date }, description: "End of metrics date range (YYYY-MM-DD). Defaults to today. Max 730-day range." }
|
|
39322
|
+
- { name: hasDelivery, in: query, schema: { type: boolean }, description: "Return only campaigns that delivered between `fromDate` and `toDate` — spend above zero, or impressions served at zero spend. Unlike `status`, which reads a campaign's CURRENT state, this filters on what happened inside the window, so a campaign that spent then and is paused today is still returned. Filters the campaign set itself, so `pagination.total` counts only matching campaigns." }
|
|
39323
|
+
- { name: minSpend, in: query, schema: { type: number, minimum: 0 }, description: "Return only campaigns whose spend between `fromDate` and `toDate` reaches this amount. Expressed in each campaign's OWN currency (the `currency` field on the campaign node): spend is stored per ad account in its native currency and one response can span several. Implies `hasDelivery`; `minSpend=0` applies no filter." }
|
|
38073
39324
|
- { name: sort, in: query, schema: { type: string, enum: [newest, oldest, spend_desc, spend_asc], default: newest }, description: "Campaign-level sort order. `newest` (default) / `oldest` order by the campaign's newest-ad createdAt. `spend_desc` / `spend_asc` order by aggregated spend in the requested date range; campaigns with no spend land at the end." }
|
|
38074
39325
|
- { name: timeIncrement, in: query, schema: { type: integer, enum: [1] }, description: "Set to `1` to also return a daily breakdown. Mirrors Meta Insights' `time_increment=1`: each node gains a `daily[]` array of per-day metrics (same fields as the aggregated `metrics`) alongside the range total, so you get per-entity daily trends in ONE call instead of calling the tree once per day. Only `1` (daily) is supported. The daily series covers the same date range and uses the same source data as `metrics`, except `reach` on Meta and TikTok: the range total is the platform's de-duplicated value, so daily reach does not sum to it. See `dailyLevel` to control which levels carry it." }
|
|
38075
39326
|
- { name: dailyLevel, in: query, schema: { type: string, enum: [campaign, adset, ad], default: campaign }, description: "Which tree levels get the `daily[]` series when `timeIncrement=1`. `campaign` (default) attaches it on campaign nodes only — the common per-campaign-trend case, and the smallest payload. `adset` adds it on ad sets too; `ad` adds it on every ad in `ads[]` as well (heaviest — a long range × up to 100 ads per ad set). Scope with `campaignId` to keep `ad`-level responses small. Ignored when `timeIncrement` is unset." }
|
|
@@ -38092,7 +39343,7 @@ paths:
|
|
|
38092
39343
|
- type: object
|
|
38093
39344
|
required: [backfillPending]
|
|
38094
39345
|
properties:
|
|
38095
|
-
backfillPending: { type: boolean,
|
|
39346
|
+
backfillPending: { type: boolean, description: 'Always true on this response. Part of the requested range is still being backfilled; retry until the request returns 200.' }
|
|
38096
39347
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
38097
39348
|
'403':
|
|
38098
39349
|
description: Ads access required. Legacy plans need the Ads add-on; included by default on usage-based plans.
|
|
@@ -38145,7 +39396,7 @@ paths:
|
|
|
38145
39396
|
- type: object
|
|
38146
39397
|
required: [backfillPending]
|
|
38147
39398
|
properties:
|
|
38148
|
-
backfillPending: { type: boolean,
|
|
39399
|
+
backfillPending: { type: boolean, description: 'Always true on this response. Part of the requested range is still being backfilled; retry until the request returns 200.' }
|
|
38149
39400
|
'400': { $ref: '#/components/responses/BadRequest' }
|
|
38150
39401
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
38151
39402
|
'403':
|
|
@@ -38294,6 +39545,7 @@ paths:
|
|
|
38294
39545
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
38295
39546
|
'404': { $ref: '#/components/responses/NotFound' }
|
|
38296
39547
|
'501': { description: "targeting or creative not supported on the platform (Meta + TikTok only)" }
|
|
39548
|
+
'502': { description: "Meta accepted the request then failed to produce the media (upload session, chunk transfer, processing timeout, or a response with no image hash). Inspect `platformError.reason`." }
|
|
38297
39549
|
delete:
|
|
38298
39550
|
x-resource-group: "ads"
|
|
38299
39551
|
operationId: deleteAd
|
|
@@ -38417,7 +39669,7 @@ paths:
|
|
|
38417
39669
|
- type: object
|
|
38418
39670
|
required: [backfillPending]
|
|
38419
39671
|
properties:
|
|
38420
|
-
backfillPending: { type: boolean,
|
|
39672
|
+
backfillPending: { type: boolean, description: 'Always true on this response. Part of the requested range is still being backfilled; retry until the request returns 200.' }
|
|
38421
39673
|
'400':
|
|
38422
39674
|
description: "Invalid parameter (e.g. an unknown `breakdowns` dimension). The message lists the offending value(s) and the supported set."
|
|
38423
39675
|
content:
|
|
@@ -38849,7 +40101,7 @@ paths:
|
|
|
38849
40101
|
- type: object
|
|
38850
40102
|
required: [backfillPending]
|
|
38851
40103
|
properties:
|
|
38852
|
-
backfillPending: { type: boolean,
|
|
40104
|
+
backfillPending: { type: boolean, description: 'Always true on this response. Part of the requested range is still being backfilled; retry until the request returns 200.' }
|
|
38853
40105
|
'400':
|
|
38854
40106
|
description: "Invalid parameter (e.g. an unknown `breakdowns` dimension). The message lists the offending value(s) and the supported set."
|
|
38855
40107
|
content:
|
|
@@ -38960,6 +40212,7 @@ paths:
|
|
|
38960
40212
|
'404': { description: "Ad not found" }
|
|
38961
40213
|
'405': { description: "Platform has no click-URL tracking surface" }
|
|
38962
40214
|
'422': { description: "Meta creative cannot be rebuilt (e.g. placement-customized/asset-feed/dark creative)" }
|
|
40215
|
+
'502': { description: "Meta accepted the request then failed to produce the media (upload session, chunk transfer, processing timeout, or a response with no image hash). Inspect `platformError.reason`." }
|
|
38963
40216
|
/v1/ads/{adId}/comments:
|
|
38964
40217
|
get:
|
|
38965
40218
|
x-resource-group: "engagement"
|
|
@@ -39584,6 +40837,7 @@ paths:
|
|
|
39584
40837
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
39585
40838
|
'422': { description: No Facebook Page found to act as the story actor }
|
|
39586
40839
|
'501': { description: Only supported on Meta (facebook/instagram) }
|
|
40840
|
+
'502': { description: "Meta accepted the request then failed to produce the media (upload session, chunk transfer, processing timeout, or a response with no image hash). Inspect `platformError.reason`." }
|
|
39587
40841
|
|
|
39588
40842
|
/v1/ads/creatives/{creativeId}:
|
|
39589
40843
|
get:
|
|
@@ -40191,8 +41445,20 @@ paths:
|
|
|
40191
41445
|
|
|
40192
41446
|
`instagramAccountId`, `destinationType` and `adSetId` are Meta-only and
|
|
40193
41447
|
return 400 on other platforms.
|
|
41448
|
+
|
|
41449
|
+
**Retries.** Boosts are NOT idempotent and can take minutes when Meta requires re-hosting an
|
|
41450
|
+
Instagram video, so do not retry on client timeout. Send an
|
|
41451
|
+
Idempotency-Key header to make retries safe: same key and body replays
|
|
41452
|
+
the original 201, and distinct keys always create distinct ads.
|
|
41453
|
+
Without the header, an identical request is treated as a retry: while
|
|
41454
|
+
one is in flight it returns 409, and within 10 minutes of a completed
|
|
41455
|
+
boost it returns the already-created ad instead of creating another.
|
|
41456
|
+
To intentionally duplicate an ad, send distinct Idempotency-Keys (or
|
|
41457
|
+
vary the body, e.g. the name).
|
|
40194
41458
|
security:
|
|
40195
41459
|
- bearerAuth: []
|
|
41460
|
+
parameters:
|
|
41461
|
+
- $ref: '#/components/parameters/IdempotencyKeyHeader'
|
|
40196
41462
|
requestBody:
|
|
40197
41463
|
required: true
|
|
40198
41464
|
content:
|
|
@@ -40217,7 +41483,7 @@ paths:
|
|
|
40217
41483
|
type: { type: string, enum: [daily, lifetime] }
|
|
40218
41484
|
instagramAccountId: { type: string, description: "Meta only. Instagram identity the ad runs AS (creative.instagram_user_id), overriding the account linked to the Page. Live-verified against a Page-post creative." }
|
|
40219
41485
|
destinationType: { type: string, enum: [INSTAGRAM_PROFILE, WEBSITE, ON_AD, MESSENGER, WHATSAPP], description: "Meta only. Ad-set destination_type — where the click LANDS, as opposed to instagramAccountId which is who the ad runs as. Lead ads force ON_AD and ignore this." }
|
|
40220
|
-
currency: { type: string, example: USD }
|
|
41486
|
+
currency: { type: string, minLength: 3, maxLength: 3, example: USD, description: "ISO 4217 currency code matching the ad account's currency. Meta only. Optional: Zernio resolves it from the ad account when omitted. The value selects the minor-unit exponent Zernio converts budget/bid amounts by before calling Meta (most currencies are cents; zero-decimal currencies like JPY/KRW are sent as-is)." }
|
|
40221
41487
|
schedule:
|
|
40222
41488
|
type: object
|
|
40223
41489
|
properties:
|
|
@@ -40406,8 +41672,9 @@ paths:
|
|
|
40406
41672
|
CTA button label. Send it together with `linkUrl` — a CTA without a
|
|
40407
41673
|
destination produces a button that goes nowhere, so sending one alone is a 400.
|
|
40408
41674
|
|
|
40409
|
-
**Meta**:
|
|
40410
|
-
|
|
41675
|
+
**Meta**: the CTA enum of POST /v1/ads/create plus
|
|
41676
|
+
`VIEW_INSTAGRAM_PROFILE`, which is accepted on boost only. For that
|
|
41677
|
+
value `linkUrl` is typically the Instagram profile URL.
|
|
40411
41678
|
|
|
40412
41679
|
**TikTok**: pass-through to `call_to_action` on the Spark Ad creative; the
|
|
40413
41680
|
platform validates the value. See TikTok's "Enumeration - Call-to-Action".
|
|
@@ -40462,6 +41729,10 @@ paths:
|
|
|
40462
41729
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
40463
41730
|
'403':
|
|
40464
41731
|
description: Ads access required. Legacy plans need the Ads add-on; included by default on usage-based plans.
|
|
41732
|
+
'409':
|
|
41733
|
+
description: |
|
|
41734
|
+
An identical boost request is already in progress (with or without
|
|
41735
|
+
an Idempotency-Key). Wait for it to finish instead of retrying.
|
|
40465
41736
|
'422':
|
|
40466
41737
|
description: |
|
|
40467
41738
|
Platform ads connection required (TikTok Ads, X Ads), missing linked
|
|
@@ -40469,13 +41740,15 @@ paths:
|
|
|
40469
41740
|
as an Identity on the target advertiser. Returned with code
|
|
40470
41741
|
`ads_connection_required`; the message includes the actionable
|
|
40471
41742
|
"TikTok Ads Manager → Assets → Identity" remediation step.
|
|
41743
|
+
Also returned as `idempotency_key_reused` when an Idempotency-Key
|
|
41744
|
+
is reused with a different request body.
|
|
40472
41745
|
|
|
40473
41746
|
/v1/ads/create:
|
|
40474
41747
|
post:
|
|
40475
41748
|
x-resource-group: "ads"
|
|
40476
41749
|
operationId: createStandaloneAd
|
|
40477
41750
|
tags: ["Ad Campaigns"]
|
|
40478
|
-
x-platforms: ["meta", "google", "tiktok", "linkedin", "pinterest", "x"]
|
|
41751
|
+
x-platforms: ["meta", "google", "tiktok", "linkedin", "pinterest", "x", "openai"]
|
|
40479
41752
|
summary: Create standalone ad
|
|
40480
41753
|
description: >-
|
|
40481
41754
|
Creates a paid ad with custom creative across Meta, Google Ads,
|
|
@@ -40580,7 +41853,11 @@ paths:
|
|
|
40580
41853
|
status:
|
|
40581
41854
|
type: string
|
|
40582
41855
|
enum: [ACTIVE, PAUSED]
|
|
40583
|
-
description: "Meta and TikTok. Publish state of the created entities. Omitted or ACTIVE publishes live (default, back-compat); PAUSED creates them paused
|
|
41856
|
+
description: "Meta and TikTok. Publish state of the created entities. Omitted or ACTIVE publishes live (default, back-compat); PAUSED creates them paused so you can review before they spend. On Meta the pause is held on the campaign this call creates, leaving the ad set and ad switched on, so a single PUT /v1/ads/campaigns/{campaignId}/status with `active` brings the whole thing live. It is held at every level instead when the pause cannot rely on the campaign: `existingCampaignId` (that campaign may be running and is never touched) or `campaignStatus: ACTIVE`. On TikTok the whole campaign > ad group > ad hierarchy stays paused."
|
|
41857
|
+
campaignStatus:
|
|
41858
|
+
type: string
|
|
41859
|
+
enum: [ACTIVE, PAUSED]
|
|
41860
|
+
description: "Meta only. Overrides `status` for the campaign level alone, so you can create a live campaign whose ad set and ad stay paused, or the reverse. Omitted, it follows `status`."
|
|
40584
41861
|
budgetLevel:
|
|
40585
41862
|
type: string
|
|
40586
41863
|
enum: [adset, campaign]
|
|
@@ -40594,7 +41871,7 @@ paths:
|
|
|
40594
41871
|
across ad sets automatically.
|
|
40595
41872
|
Meta requires the budget at exactly one level, never both. Non-Meta platforms ignore
|
|
40596
41873
|
this field. Ignored on the attach shape (`adSetId`), which inherits the existing budget.
|
|
40597
|
-
currency: { type: string }
|
|
41874
|
+
currency: { type: string, minLength: 3, maxLength: 3, description: "ISO 4217 currency code matching the ad account's currency (e.g. `USD`). Meta only. Optional: Zernio resolves it from the ad account when omitted. The value selects the minor-unit exponent Zernio converts budget/bid amounts by before calling Meta (most currencies are cents; zero-decimal currencies like JPY/KRW are sent as-is)." }
|
|
40598
41875
|
headline: { type: string, description: "Required for Meta, Google, Pinterest, LinkedIn, and OpenAI Ads on legacy + attach shapes (skip for multi-creative — use `creatives[].headline`). Ignored for TikTok and X/Twitter. Max: Meta=255, Google=30, Pinterest=100, LinkedIn=400, OpenAI=50 (min 3). On LinkedIn this is the ad's headline (the bold text on the creative); for traffic ads it's the link card title. On OpenAI Ads this is the chat card's title." }
|
|
40599
41876
|
longHeadline: { type: string, maxLength: 90, description: "Google Display only — defaults to `headline` if omitted. On LinkedIn, reused as the optional secondary description text on traffic (link) ads; omitted if not provided." }
|
|
40600
41877
|
body: { type: string, description: "Required on legacy + attach shapes. For X/Twitter this is the tweet text (max 280 chars including a ~24-char URL when `linkUrl` is set). On LinkedIn this is the post commentary (the intro text shown above the ad). On OpenAI Ads this is the chat card's body text. Max: Google=90, Pinterest=500, OpenAI=100." }
|
|
@@ -40615,7 +41892,7 @@ paths:
|
|
|
40615
41892
|
properties:
|
|
40616
41893
|
url: { type: string, format: uri, description: "Public URL of the video. Meta: uploaded via chunked transfer on /act_X/advideos, then the request blocks on Meta's transcoding until status.video_status === 'ready'. LinkedIn: uploaded via the Videos API (multipart), then the request blocks until LinkedIn finishes transcoding (status AVAILABLE) — short clips take ~10-30s. Provide either `url` or `id`."}
|
|
40617
41894
|
id: { type: string, description: "Meta only. Reuse a video ALREADY uploaded to this ad account instead of re-uploading the file: pass the `videoId` returned by a previous create. Wins over `url`, so N ads that differ only in copy share one upload (`existingCreativeId` only covers the identical-copy case). Provide either `url` or `id`."}
|
|
40618
|
-
thumbnailUrl: { type: string, format: uri, description: "Public URL of a still-image thumbnail for the video. OPTIONAL: when omitted on Meta, the poster is auto-generated from Meta's own preferred video thumbnail (the same candidates Ads Manager shows), so video ads publish without supplying one. Provide it to control the poster frame exactly (uploaded as an ad image and referenced in object_story_spec.video_data). Ignored by LinkedIn (auto-generated poster frame)." }
|
|
41895
|
+
thumbnailUrl: { type: string, format: uri, description: "Public URL of a still-image thumbnail for the video. OPTIONAL: when omitted on Meta, the poster is auto-generated from Meta's own preferred video thumbnail (the same candidates Ads Manager shows), so video ads usually publish without supplying one. When Meta produces no candidate the request fails with a 502 platform_error (reason: video_thumbnail_unavailable) — retry, or supply this field. Provide it to control the poster frame exactly (uploaded as an ad image and referenced in object_story_spec.video_data). Ignored by LinkedIn (auto-generated poster frame)." }
|
|
40619
41896
|
creatives:
|
|
40620
41897
|
type: array
|
|
40621
41898
|
minItems: 1
|
|
@@ -40636,7 +41913,7 @@ paths:
|
|
|
40636
41913
|
imageUrl: { type: string, format: uri, description: "Image creative. Mutually exclusive with `video`." }
|
|
40637
41914
|
video:
|
|
40638
41915
|
type: object
|
|
40639
|
-
description: "Video creative for this entry. Mutually exclusive with `imageUrl`. thumbnailUrl is optional
|
|
41916
|
+
description: "Video creative for this entry. Mutually exclusive with `imageUrl`. thumbnailUrl is optional: when omitted, the poster is auto-generated from Meta's preferred video thumbnail, and the request fails with a 502 platform_error (reason: video_thumbnail_unavailable) if Meta produces no candidate."
|
|
40640
41917
|
required: [url]
|
|
40641
41918
|
properties:
|
|
40642
41919
|
url: { type: string, format: uri }
|
|
@@ -40657,8 +41934,9 @@ paths:
|
|
|
40657
41934
|
The attached ad takes the full single-creative surface:
|
|
40658
41935
|
`headline`/`body`/`description`/`callToAction` plus either
|
|
40659
41936
|
`imageUrl`/`video` OR `placementAssets` (its own per-placement
|
|
40660
|
-
Feed/Story assets)
|
|
40661
|
-
|
|
41937
|
+
Feed/Story assets) OR `translations`/`defaultLocale` (its own
|
|
41938
|
+
per-locale asset feed, Meta only), and `leadGenFormId` when
|
|
41939
|
+
the target is a lead ad set (the parent must be ON_AD, true for ad sets
|
|
40662
41940
|
created via goal `lead_generation`; Meta rejects a formless ad
|
|
40663
41941
|
there, so pass the form on EVERY attached ad). This is the way
|
|
40664
41942
|
to build N full ads sharing one ad set: create the first ad
|
|
@@ -40887,8 +42165,9 @@ paths:
|
|
|
40887
42165
|
description: |
|
|
40888
42166
|
Meta only. Override the Instagram account the ad is delivered as — pass an Instagram
|
|
40889
42167
|
Business Account ID (e.g. 17841...), mapped to the creative's `instagram_user_id`.
|
|
40890
|
-
When omitted we
|
|
40891
|
-
|
|
42168
|
+
When omitted we use the Instagram actor Meta already runs the Page's other ads as,
|
|
42169
|
+
falling back to the Page's page-backed Instagram account. Useful when a Page has more
|
|
42170
|
+
than one eligible IG account.
|
|
40892
42171
|
dynamicCreative:
|
|
40893
42172
|
type: object
|
|
40894
42173
|
description: |
|
|
@@ -40998,8 +42277,8 @@ paths:
|
|
|
40998
42277
|
works on a normal ad may be rejected with "The following images have invalid
|
|
40999
42278
|
dimensions for Dynamic Creative" (subcode 1885558). Video is not affected.
|
|
41000
42279
|
|
|
41001
|
-
Mutually exclusive with `dynamicCreative`, `placementAssets`, `carouselCards
|
|
41002
|
-
`existingCreativeId`
|
|
42280
|
+
Mutually exclusive with `dynamicCreative`, `placementAssets`, `carouselCards`,
|
|
42281
|
+
`existingCreativeId` and `creatives[]`. Meta allows one `asset_feed_spec` shape per creative.
|
|
41003
42282
|
items:
|
|
41004
42283
|
type: object
|
|
41005
42284
|
required: [locale, headline, body, description]
|
|
@@ -41135,6 +42414,8 @@ paths:
|
|
|
41135
42414
|
Deprecated: send it inside `platformSpecificData` instead (Meta today; TikTok's nested shape is planned). The flat field keeps working during the deprecation window; sending both shapes returns a 400.
|
|
41136
42415
|
|
|
41137
42416
|
Meta bid strategy applied to the ad set.
|
|
42417
|
+
|
|
42418
|
+
OpenAI Ads: required on every ad group via this flat field, the only channel it supports (`platformSpecificData` is Meta/LinkedIn-only and returns 400 for OpenAI). No auto-bid option exists; send `LOWEST_COST_WITH_BID_CAP` or `COST_CAP` together with `bidAmount`, omitting it returns 400.
|
|
41138
42419
|
bidAmount:
|
|
41139
42420
|
type: number
|
|
41140
42421
|
deprecated: true
|
|
@@ -41261,6 +42542,21 @@ paths:
|
|
|
41261
42542
|
Ads (`POST /v1/ads/boost`) always use `TT_USER` regardless
|
|
41262
42543
|
of this field — TikTok requires the original organic
|
|
41263
42544
|
post's author identity for Spark.
|
|
42545
|
+
smartPlus:
|
|
42546
|
+
type: boolean
|
|
42547
|
+
description: |
|
|
42548
|
+
TikTok only. Creates the ad as a TikTok Upgraded Smart+
|
|
42549
|
+
campaign: TikTok automates targeting, bidding and delivery. Supports goals
|
|
42550
|
+
`conversions` (Smart+ Web Conversions), `lead_generation` (Smart+ Lead
|
|
42551
|
+
Generation with a website form on `linkUrl`; TikTok Instant Forms not supported)
|
|
42552
|
+
and `app_promotion` (Smart+ App installs; the ad's destination is the app store,
|
|
42553
|
+
so `linkUrl` is not used). The web goals require `promotedObject.pixelId` AND
|
|
42554
|
+
`promotedObject.customEventType`; `app_promotion` requires
|
|
42555
|
+
`promotedObject.applicationId` instead.
|
|
42556
|
+
Targeting works like on any TikTok ad (defaults to `countries: ["US"]` when
|
|
42557
|
+
omitted); TikTok automates delivery within it.
|
|
42558
|
+
The budget lives on the Smart+ campaign (Campaign Budget Optimization); a `lifetime`
|
|
42559
|
+
budget additionally requires `endDate`. Cannot be combined with `adSetId`.
|
|
41264
42560
|
promotedObject:
|
|
41265
42561
|
type: object
|
|
41266
42562
|
description: |
|
|
@@ -41276,12 +42572,15 @@ paths:
|
|
|
41276
42572
|
|
|
41277
42573
|
Other Meta goals (engagement, traffic, awareness, video_views) ignore this field.
|
|
41278
42574
|
|
|
41279
|
-
**TikTok**:
|
|
42575
|
+
**TikTok**: used by `goal: conversions` and the Smart+ goals (`smartPlus: true`).
|
|
41280
42576
|
- `pixelId` maps to the ad group's `pixel_id`. Required: a TikTok website-conversion
|
|
41281
42577
|
ad group without a pixel is rejected with `40002: Please select a pixel`.
|
|
41282
42578
|
- `customEventType` maps to the ad group's `optimization_event` (the pixel event to
|
|
41283
|
-
optimise for). Optional
|
|
42579
|
+
optimise for). Optional on the regular conversions flow, required on Smart+.
|
|
41284
42580
|
See the `customEventType` field below for the valid TikTok codes.
|
|
42581
|
+
- `applicationId` (Smart+ `goal: app_promotion` only) maps to the ad group's `app_id`:
|
|
42582
|
+
the App ID of an app registered on the TikTok Ads account (Assets → Events →
|
|
42583
|
+
App Events). Install optimization needs the app's MMP tracking configured.
|
|
41285
42584
|
|
|
41286
42585
|
The remaining `promotedObject.*` fields are Meta-only. Platforms other than
|
|
41287
42586
|
Meta and TikTok ignore `promotedObject` entirely.
|
|
@@ -41290,6 +42589,9 @@ paths:
|
|
|
41290
42589
|
type: string
|
|
41291
42590
|
description: |
|
|
41292
42591
|
Pixel ID. **Meta:** Facebook Pixel ID, required for `goal: conversions`.
|
|
42592
|
+
Requires `customEventType` alongside it; Meta rejects any promoted_object
|
|
42593
|
+
carrying `pixel_id` without `custom_event_type` (error_subcode 1885014),
|
|
42594
|
+
even when `customConversionId` is also present.
|
|
41293
42595
|
**TikTok:** TikTok Pixel ID, required for `goal: conversions`.
|
|
41294
42596
|
To discover the pixels an ad account can use, call
|
|
41295
42597
|
`GET /v1/accounts/{accountId}/tracking-tags?adAccountId=act_...` (each entry
|
|
@@ -41339,7 +42641,12 @@ paths:
|
|
|
41339
42641
|
description: "App Store / Play Store listing URL. Required for `goal: app_promotion`."
|
|
41340
42642
|
customConversionId:
|
|
41341
42643
|
type: string
|
|
41342
|
-
description:
|
|
42644
|
+
description: |
|
|
42645
|
+
Custom Conversion ID, when optimising against one instead of a standard
|
|
42646
|
+
event. Accepted alone by this API, without `pixelId` or `customEventType`.
|
|
42647
|
+
If `pixelId` is also sent, `customEventType` is still required on the
|
|
42648
|
+
promoted_object (Meta rejects `pixel_id` without `custom_event_type`,
|
|
42649
|
+
error_subcode 1885014).
|
|
41343
42650
|
productCatalogId:
|
|
41344
42651
|
type: string
|
|
41345
42652
|
description: Catalog ID for catalog/Advantage+ Shopping campaigns.
|
|
@@ -41398,6 +42705,16 @@ paths:
|
|
|
41398
42705
|
description: Ads access required. Legacy plans need the Ads add-on; included by default on usage-based plans.
|
|
41399
42706
|
'422':
|
|
41400
42707
|
description: Platform ads connection required (TikTok Ads, X Ads) or missing linked account
|
|
42708
|
+
'502':
|
|
42709
|
+
description: |
|
|
42710
|
+
The platform rejected the request, or failed to produce media the ad
|
|
42711
|
+
needs (e.g. Meta generated no poster for an uploaded video when no
|
|
42712
|
+
`video.thumbnailUrl` was supplied). Inspect `platformError` for the
|
|
42713
|
+
upstream payload. Failures we raise carry a `reason`; a payload
|
|
42714
|
+
forwarded verbatim from Meta may not. On the `creatives[]` shape a
|
|
42715
|
+
missing poster also carries `creativeIndex` and `videoUrl` to
|
|
42716
|
+
identify the entry. An upstream 4xx status is forwarded instead
|
|
42717
|
+
of 502.
|
|
41401
42718
|
|
|
41402
42719
|
/v1/ads/leads:
|
|
41403
42720
|
get:
|
|
@@ -41438,16 +42755,16 @@ paths:
|
|
|
41438
42755
|
type: object
|
|
41439
42756
|
properties:
|
|
41440
42757
|
id: { type: string, description: Zernio lead id. }
|
|
41441
|
-
leadgenId: { type: string, description: Meta lead id. }
|
|
42758
|
+
leadgenId: { type: string, description: 'Meta lead id. On LinkedIn, the leadFormResponse id.' }
|
|
41442
42759
|
formId: { type: string }
|
|
41443
42760
|
formName: { type: [string, "null"] }
|
|
41444
42761
|
accountId: { type: string }
|
|
41445
42762
|
adId: { type: [string, "null"] }
|
|
41446
42763
|
adsetId: { type: [string, "null"] }
|
|
41447
|
-
campaignId: { type: [string, "null"] }
|
|
42764
|
+
campaignId: { type: [string, "null"], description: 'On LinkedIn, this is the LinkedIn Campaign id, which corresponds to platformAdSetId on GET /v1/ads (LinkedIn''s Campaign Group is Zernio''s campaign).' }
|
|
41448
42765
|
isOrganic: { type: boolean }
|
|
41449
42766
|
createdTime: { type: [string, "null"], description: ISO 8601. }
|
|
41450
|
-
fields: { type: object, additionalProperties: { type: string }, description:
|
|
42767
|
+
fields: { type: object, additionalProperties: { type: string }, description: 'Question key → answer. On LinkedIn, the key is the lowercased predefinedField, else the question name, else the numeric questionId; multiple-choice values are option labels (unlike Meta, which returns the option key).' }
|
|
41451
42768
|
fieldData: { type: array, items: { type: object }, description: "Raw Meta field_data." }
|
|
41452
42769
|
pagination:
|
|
41453
42770
|
type: object
|
|
@@ -41803,6 +43120,7 @@ paths:
|
|
|
41803
43120
|
'400': { description: "Invalid input, or Meta rejected the image" }
|
|
41804
43121
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
41805
43122
|
'501': { description: Only supported on Meta (facebook/instagram) }
|
|
43123
|
+
'502': { description: "Meta accepted the request then failed to produce the media (upload session, chunk transfer, processing timeout, or a response with no image hash). Inspect `platformError.reason`." }
|
|
41806
43124
|
|
|
41807
43125
|
get:
|
|
41808
43126
|
x-resource-group: "ads"
|
|
@@ -41906,6 +43224,28 @@ paths:
|
|
|
41906
43224
|
markets, and every id is usable in `regions`/`cities`/`metros` keys on
|
|
41907
43225
|
`POST /v1/ads/create`.
|
|
41908
43226
|
|
|
43227
|
+
LinkedIn geo searches also return every matching level in one list, and
|
|
43228
|
+
neither `geoType` nor `countryCode` is applied: LinkedIn's typeahead only
|
|
43229
|
+
returns a name and a URN per result, with no level or country field to
|
|
43230
|
+
filter on. Every result has `type` set to `location`, and its id is a
|
|
43231
|
+
`urn:li:geo:*` URN usable as a `regions[].key` on `POST /v1/ads/create`,
|
|
43232
|
+
`POST /v1/ads/boost` and `POST /v1/ads/targeting/reach-estimate`.
|
|
43233
|
+
|
|
43234
|
+
Pinterest resolves against three whole-catalog endpoints (interests, locations,
|
|
43235
|
+
regions) with no server-side query or pagination, so matching, ranking and the
|
|
43236
|
+
`limit` cutoff all happen in Zernio; the catalog is independent of any ad account
|
|
43237
|
+
and results never carry `audienceSize`. Names come back localized to the connected
|
|
43238
|
+
Pinterest account's language (there is no way to force a locale), so match against
|
|
43239
|
+
whatever language that account returns. `geoType` routes to a different catalog:
|
|
43240
|
+
`country` and `metro_area` read the locations catalog (`type` is `country` or
|
|
43241
|
+
`metro`); `region` reads the regions catalog (`type` is `region`, its id a
|
|
43242
|
+
`regions[].key` on `POST /v1/ads/create`); `all` and the default `city` merge both
|
|
43243
|
+
catalogs with honest per-entry `type`s, since Pinterest has no city-level catalog
|
|
43244
|
+
and `city` is an alias for `all`, not a literal city search. `zip`, `subcity`,
|
|
43245
|
+
`neighborhood`, `place` and `geo_market` return a 400: Pinterest exposes no
|
|
43246
|
+
postal-code catalog, pass postal codes directly as `targeting.zips: [{ key }]` on
|
|
43247
|
+
`POST /v1/ads/create`.
|
|
43248
|
+
|
|
41909
43249
|
For geo queries, `q` should contain only the locality name (e.g. `"Amsterdam"`,
|
|
41910
43250
|
not `"Amsterdam, NL"`). Use `countryCode` to disambiguate.
|
|
41911
43251
|
security:
|
|
@@ -41914,7 +43254,7 @@ paths:
|
|
|
41914
43254
|
- { name: accountId, in: query, required: true, schema: { type: string }, description: "Social account ID (a connected account on the target ad platform)." }
|
|
41915
43255
|
- { name: q, in: query, required: true, schema: { type: string }, description: "Search query. For geo, the locality name only (no region/country suffix)." }
|
|
41916
43256
|
- { name: dimension, in: query, required: false, schema: { type: string, enum: [geo, interest, behavior, income], default: interest }, description: "What to search. `geo` resolves locations (scope further with `geoType`), `interest`/`behavior` resolve audience entities, `income` resolves income-tier options. Defaults to `interest` for backward compatibility with the deprecated /v1/ads/interests alias." }
|
|
41917
|
-
- { name: geoType, in: query, required: false, schema: { type: string, enum: [country, region, city, zip,
|
|
43257
|
+
- { name: geoType, in: query, required: false, schema: { type: string, enum: [all, country, region, city, subcity, neighborhood, place, zip, metro_area, geo_market], default: city }, description: "Only used when `dimension=geo`. The kind of location to resolve. `all` searches every type in one relevance-ranked call. Defaults to `city`." }
|
|
41918
43258
|
- { name: countryCode, in: query, required: false, schema: { type: string, minLength: 2, maxLength: 2 }, description: "ISO 3166-1 alpha-2 country code (e.g. NL) to scope a geo search." }
|
|
41919
43259
|
- { name: limit, in: query, required: false, schema: { type: integer, minimum: 1, maximum: 100, default: 25 }, description: "Maximum results to return." }
|
|
41920
43260
|
responses:
|
|
@@ -41933,7 +43273,7 @@ paths:
|
|
|
41933
43273
|
properties:
|
|
41934
43274
|
id: { type: string, description: "The platform's opaque id. Use as a geo `key` (regions/cities/zips/metros) or an entity `id` (interests/behaviors) in TargetingSpec." }
|
|
41935
43275
|
name: { type: string, description: "Human-readable label." }
|
|
41936
|
-
type: { type: string, description: "What the result is (e.g. city, region, country, zip, metro, interest, behavior, income)." }
|
|
43276
|
+
type: { type: string, description: "What the result is (e.g. city, region, country, zip, metro, location, interest, behavior, income)." }
|
|
41937
43277
|
path: { type: array, items: { type: string }, description: "Optional breadcrumb of parent labels (e.g. ['United States', 'California', 'Los Angeles']). Disambiguates same-named results." }
|
|
41938
43278
|
audienceSize: { type: [integer, "null"], description: "Optional estimated reachable users for this option, when the platform returns it." }
|
|
41939
43279
|
'400':
|
|
@@ -43788,6 +45128,7 @@ paths:
|
|
|
43788
45128
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
43789
45129
|
'404': { description: Account not found }
|
|
43790
45130
|
'422': { description: "No Facebook Page resolved for the account" }
|
|
45131
|
+
'502': { description: "Meta accepted the request then failed to produce the media (upload session, chunk transfer, processing timeout, or a response with no image hash). Inspect `platformError.reason`." }
|
|
43791
45132
|
|
|
43792
45133
|
/v1/ads/call:
|
|
43793
45134
|
post:
|
|
@@ -43827,6 +45168,7 @@ paths:
|
|
|
43827
45168
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
43828
45169
|
'404': { description: Account not found }
|
|
43829
45170
|
'422': { description: "No Facebook Page resolved for the account" }
|
|
45171
|
+
'502': { description: "Meta accepted the request then failed to produce the media (upload session, chunk transfer, processing timeout, or a response with no image hash). Inspect `platformError.reason`." }
|
|
43830
45172
|
|
|
43831
45173
|
/v1/ads/ctwa:
|
|
43832
45174
|
post:
|
|
@@ -44018,6 +45360,7 @@ paths:
|
|
|
44018
45360
|
'403': { description: 'Ads access required (Ads add-on on legacy plans, included on usage-based plans), or the Meta token lacks ads permissions (reconnect required).' }
|
|
44019
45361
|
'404': { description: Account not found or not accessible. }
|
|
44020
45362
|
'405': { description: Platform does not support listing tracking tags. }
|
|
45363
|
+
'502': { description: 'Meta was unreachable or returned an unclassified error (type: platform_error; the raw Meta payload is in platformError). Retryable.' }
|
|
44021
45364
|
|
|
44022
45365
|
post:
|
|
44023
45366
|
x-resource-group: "ads"
|
|
@@ -44083,6 +45426,7 @@ paths:
|
|
|
44083
45426
|
'404': { description: Account not found or not accessible. }
|
|
44084
45427
|
'405': { description: Platform does not support creating tracking tags. }
|
|
44085
45428
|
'422': { description: 'OpenAI Ads only: the ad account is not enabled for pixel management. Contact your OpenAI partner representative.' }
|
|
45429
|
+
'502': { description: 'Meta was unreachable or returned an unclassified error (type: platform_error; the raw Meta payload is in platformError). Creating a pixel is NOT idempotent, so before retrying confirm with GET /v1/accounts/{accountId}/tracking-tags that no pixel was created.' }
|
|
44086
45430
|
|
|
44087
45431
|
/v1/accounts/{accountId}/tracking-tags/{tagId}:
|
|
44088
45432
|
get:
|
|
@@ -44116,6 +45460,7 @@ paths:
|
|
|
44116
45460
|
'403': { description: 'Ads access required (Ads add-on on legacy plans, included on usage-based plans), or the Meta token lacks ads permissions (reconnect required).' }
|
|
44117
45461
|
'404': { description: Account or tracking tag not found. }
|
|
44118
45462
|
'405': { description: Platform does not support fetching a tracking tag. }
|
|
45463
|
+
'502': { description: 'Meta was unreachable or returned an unclassified error (type: platform_error; the raw Meta payload is in platformError). Retryable.' }
|
|
44119
45464
|
|
|
44120
45465
|
patch:
|
|
44121
45466
|
x-resource-group: "ads"
|
|
@@ -44182,6 +45527,7 @@ paths:
|
|
|
44182
45527
|
'403': { description: 'Ads access required (Ads add-on on legacy plans, included on usage-based plans), or the Meta token lacks ads permissions (reconnect required).' }
|
|
44183
45528
|
'404': { description: Account or tracking tag not found. }
|
|
44184
45529
|
'405': { description: Platform does not support updating tracking tags. }
|
|
45530
|
+
'502': { description: 'Meta was unreachable or returned an unclassified error (type: platform_error; the raw Meta payload is in platformError). Retryable.' }
|
|
44185
45531
|
|
|
44186
45532
|
/v1/accounts/{accountId}/tracking-tags/{tagId}/shared-accounts:
|
|
44187
45533
|
get:
|
|
@@ -44212,6 +45558,7 @@ paths:
|
|
|
44212
45558
|
'403': { description: 'Ads access required (Ads add-on on legacy plans, included on usage-based plans), or the Meta token lacks ads permissions (reconnect required).' }
|
|
44213
45559
|
'404': { description: Account or tracking tag not found. }
|
|
44214
45560
|
'405': { description: Platform does not support shared accounts. }
|
|
45561
|
+
'502': { description: 'Meta was unreachable or returned an unclassified error (type: platform_error; the raw Meta payload is in platformError). Retryable.' }
|
|
44215
45562
|
|
|
44216
45563
|
post:
|
|
44217
45564
|
x-resource-group: "ads"
|
|
@@ -44254,6 +45601,7 @@ paths:
|
|
|
44254
45601
|
'403': { description: 'Ads access required (Ads add-on on legacy plans, included on usage-based plans), or the Meta token lacks ads permissions (reconnect required).' }
|
|
44255
45602
|
'404': { description: Account or tracking tag not found. }
|
|
44256
45603
|
'405': { description: Platform does not support shared accounts. }
|
|
45604
|
+
'502': { description: 'Meta was unreachable or returned an unclassified error (type: platform_error; the raw Meta payload is in platformError). Retryable.' }
|
|
44257
45605
|
|
|
44258
45606
|
delete:
|
|
44259
45607
|
x-resource-group: "ads"
|
|
@@ -44278,6 +45626,7 @@ paths:
|
|
|
44278
45626
|
'403': { description: 'Ads access required (Ads add-on on legacy plans, included on usage-based plans), or the Meta token lacks ads permissions (reconnect required).' }
|
|
44279
45627
|
'404': { description: Account or tracking tag not found. }
|
|
44280
45628
|
'405': { description: Platform does not support shared accounts. }
|
|
45629
|
+
'502': { description: 'Meta was unreachable or returned an unclassified error (type: platform_error; the raw Meta payload is in platformError). Retryable.' }
|
|
44281
45630
|
|
|
44282
45631
|
/v1/accounts/{accountId}/tracking-tags/{tagId}/stats:
|
|
44283
45632
|
get:
|
|
@@ -44345,6 +45694,448 @@ paths:
|
|
|
44345
45694
|
'403': { description: 'Ads access required (Ads add-on on legacy plans, included on usage-based plans), or the Meta token lacks ads permissions (reconnect required).' }
|
|
44346
45695
|
'404': { description: Account or tracking tag not found. }
|
|
44347
45696
|
'405': { description: Platform does not support tracking-tag stats. }
|
|
45697
|
+
'502': { description: 'Meta was unreachable or returned an unclassified error (type: platform_error; the raw Meta payload is in platformError). Retryable.' }
|
|
45698
|
+
|
|
45699
|
+
/v1/accounts/{accountId}/blogs:
|
|
45700
|
+
get:
|
|
45701
|
+
x-resource-group: "publishing"
|
|
45702
|
+
operationId: listBlogs
|
|
45703
|
+
tags: ["Blogs"]
|
|
45704
|
+
x-platforms: ["shopify"]
|
|
45705
|
+
summary: List blogs
|
|
45706
|
+
description: |
|
|
45707
|
+
Lists the blogs on the connected store, newest-first as the platform
|
|
45708
|
+
returns them. Cursor-paginated: pass `limit` (1-50, default 20) and the
|
|
45709
|
+
`cursor` from a previous response's `nextCursor`; `nextCursor` is null
|
|
45710
|
+
when there are no more pages.
|
|
45711
|
+
|
|
45712
|
+
Supported on Shopify (platform `shopify`). Accounts on platforms
|
|
45713
|
+
without blogs support return 400; a blogs-capable platform that lacks
|
|
45714
|
+
this specific operation returns 405.
|
|
45715
|
+
security:
|
|
45716
|
+
- bearerAuth: []
|
|
45717
|
+
parameters:
|
|
45718
|
+
- { name: accountId, in: path, required: true, schema: { type: string }, description: 'Connected Shopify SocialAccount id.' }
|
|
45719
|
+
- { name: limit, in: query, required: false, schema: { type: integer, minimum: 1, maximum: 50, default: 20 }, description: 'Page size (1-50).' }
|
|
45720
|
+
- { name: cursor, in: query, required: false, schema: { type: string }, description: 'Opaque cursor from a previous response. Omit for the first page.' }
|
|
45721
|
+
responses:
|
|
45722
|
+
'200':
|
|
45723
|
+
description: Blogs listed
|
|
45724
|
+
content:
|
|
45725
|
+
application/json:
|
|
45726
|
+
schema:
|
|
45727
|
+
type: object
|
|
45728
|
+
properties:
|
|
45729
|
+
platform: { type: string, enum: [shopify] }
|
|
45730
|
+
blogs:
|
|
45731
|
+
type: array
|
|
45732
|
+
items: { $ref: '#/components/schemas/Blog' }
|
|
45733
|
+
nextCursor: { type: [string, "null"], description: 'Cursor for the next page; null when there are no more pages.' }
|
|
45734
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
45735
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
45736
|
+
'403': { description: 'The platform rejected the request (code insufficient_permissions); reconnect the Shopify account to restore access.' }
|
|
45737
|
+
'404': { description: 'Account not found or not accessible (code account_not_found).' }
|
|
45738
|
+
'405': { description: Platform does not support listing blogs. }
|
|
45739
|
+
'429': { description: 'Rate limited, either by Zernio or by Shopify. Retry later.' }
|
|
45740
|
+
|
|
45741
|
+
post:
|
|
45742
|
+
x-resource-group: "publishing"
|
|
45743
|
+
operationId: createBlog
|
|
45744
|
+
tags: ["Blogs"]
|
|
45745
|
+
x-platforms: ["shopify"]
|
|
45746
|
+
summary: Create a blog
|
|
45747
|
+
description: |
|
|
45748
|
+
Creates a blog on the connected store. The platform generates the URL
|
|
45749
|
+
`handle` from the title when omitted.
|
|
45750
|
+
|
|
45751
|
+
Supported on Shopify (platform `shopify`). Accounts on platforms
|
|
45752
|
+
without blogs support return 400; a blogs-capable platform that lacks
|
|
45753
|
+
this specific operation returns 405.
|
|
45754
|
+
security:
|
|
45755
|
+
- bearerAuth: []
|
|
45756
|
+
parameters:
|
|
45757
|
+
- { name: accountId, in: path, required: true, schema: { type: string }, description: 'Connected Shopify SocialAccount id.' }
|
|
45758
|
+
requestBody:
|
|
45759
|
+
required: true
|
|
45760
|
+
content:
|
|
45761
|
+
application/json:
|
|
45762
|
+
schema:
|
|
45763
|
+
type: object
|
|
45764
|
+
required: [title]
|
|
45765
|
+
properties:
|
|
45766
|
+
title: { type: string, minLength: 1 }
|
|
45767
|
+
handle: { type: string, minLength: 1, description: 'URL slug. Generated from the title when omitted.' }
|
|
45768
|
+
responses:
|
|
45769
|
+
'201':
|
|
45770
|
+
description: Blog created
|
|
45771
|
+
content:
|
|
45772
|
+
application/json:
|
|
45773
|
+
schema:
|
|
45774
|
+
type: object
|
|
45775
|
+
properties:
|
|
45776
|
+
platform: { type: string, enum: [shopify] }
|
|
45777
|
+
blog: { $ref: '#/components/schemas/Blog' }
|
|
45778
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
45779
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
45780
|
+
'403': { description: 'The platform rejected the request (code insufficient_permissions); reconnect the Shopify account to restore access.' }
|
|
45781
|
+
'404': { description: 'Account not found or not accessible (code account_not_found).' }
|
|
45782
|
+
'405': { description: Platform does not support creating blogs. }
|
|
45783
|
+
'429': { description: 'Rate limited, either by Zernio or by Shopify. Retry later.' }
|
|
45784
|
+
|
|
45785
|
+
/v1/accounts/{accountId}/blogs/{blogId}:
|
|
45786
|
+
get:
|
|
45787
|
+
x-resource-group: "publishing"
|
|
45788
|
+
operationId: getBlog
|
|
45789
|
+
tags: ["Blogs"]
|
|
45790
|
+
x-platforms: ["shopify"]
|
|
45791
|
+
summary: Get a blog
|
|
45792
|
+
description: |
|
|
45793
|
+
Fetches a single blog. `blogId` is the platform's numeric blog id from
|
|
45794
|
+
`GET /v1/accounts/{accountId}/blogs`, not a Zernio id.
|
|
45795
|
+
|
|
45796
|
+
Supported on Shopify (platform `shopify`). Accounts on platforms
|
|
45797
|
+
without blogs support return 400; a blogs-capable platform that lacks
|
|
45798
|
+
this specific operation returns 405.
|
|
45799
|
+
security:
|
|
45800
|
+
- bearerAuth: []
|
|
45801
|
+
parameters:
|
|
45802
|
+
- { name: accountId, in: path, required: true, schema: { type: string }, description: 'Connected Shopify SocialAccount id.' }
|
|
45803
|
+
- { name: blogId, in: path, required: true, schema: { type: string, pattern: '^\d+$' }, description: 'Platform-native numeric blog id. Non-numeric values return 400.' }
|
|
45804
|
+
responses:
|
|
45805
|
+
'200':
|
|
45806
|
+
description: Blog fetched
|
|
45807
|
+
content:
|
|
45808
|
+
application/json:
|
|
45809
|
+
schema:
|
|
45810
|
+
type: object
|
|
45811
|
+
properties:
|
|
45812
|
+
platform: { type: string, enum: [shopify] }
|
|
45813
|
+
blog: { $ref: '#/components/schemas/Blog' }
|
|
45814
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
45815
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
45816
|
+
'403': { description: 'The platform rejected the request (code insufficient_permissions); reconnect the Shopify account to restore access.' }
|
|
45817
|
+
'404': { description: 'Account not found or not accessible (code account_not_found), or blog not found (code blog_not_found).' }
|
|
45818
|
+
'405': { description: Platform does not support fetching a blog. }
|
|
45819
|
+
'429': { description: 'Rate limited, either by Zernio or by Shopify. Retry later.' }
|
|
45820
|
+
|
|
45821
|
+
patch:
|
|
45822
|
+
x-resource-group: "publishing"
|
|
45823
|
+
operationId: updateBlog
|
|
45824
|
+
tags: ["Blogs"]
|
|
45825
|
+
x-platforms: ["shopify"]
|
|
45826
|
+
summary: Update a blog
|
|
45827
|
+
description: |
|
|
45828
|
+
Partial-updates a blog. Send any subset of `title` and `handle`; at
|
|
45829
|
+
least one field is required (an empty body returns 400).
|
|
45830
|
+
|
|
45831
|
+
Supported on Shopify (platform `shopify`). Accounts on platforms
|
|
45832
|
+
without blogs support return 400; a blogs-capable platform that lacks
|
|
45833
|
+
this specific operation returns 405.
|
|
45834
|
+
security:
|
|
45835
|
+
- bearerAuth: []
|
|
45836
|
+
parameters:
|
|
45837
|
+
- { name: accountId, in: path, required: true, schema: { type: string }, description: 'Connected Shopify SocialAccount id.' }
|
|
45838
|
+
- { name: blogId, in: path, required: true, schema: { type: string, pattern: '^\d+$' }, description: 'Platform-native numeric blog id. Non-numeric values return 400.' }
|
|
45839
|
+
requestBody:
|
|
45840
|
+
required: true
|
|
45841
|
+
content:
|
|
45842
|
+
application/json:
|
|
45843
|
+
schema:
|
|
45844
|
+
type: object
|
|
45845
|
+
description: 'At least one field is required.'
|
|
45846
|
+
properties:
|
|
45847
|
+
title: { type: string, minLength: 1 }
|
|
45848
|
+
handle: { type: string, minLength: 1, description: 'URL slug. Changing it changes the blog URL on the store.' }
|
|
45849
|
+
responses:
|
|
45850
|
+
'200':
|
|
45851
|
+
description: Blog updated
|
|
45852
|
+
content:
|
|
45853
|
+
application/json:
|
|
45854
|
+
schema:
|
|
45855
|
+
type: object
|
|
45856
|
+
properties:
|
|
45857
|
+
platform: { type: string, enum: [shopify] }
|
|
45858
|
+
blog: { $ref: '#/components/schemas/Blog' }
|
|
45859
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
45860
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
45861
|
+
'403': { description: 'The platform rejected the request (code insufficient_permissions); reconnect the Shopify account to restore access.' }
|
|
45862
|
+
'404': { description: 'Account not found or not accessible (code account_not_found), or blog not found (code blog_not_found).' }
|
|
45863
|
+
'405': { description: Platform does not support updating a blog. }
|
|
45864
|
+
'429': { description: 'Rate limited, either by Zernio or by Shopify. Retry later.' }
|
|
45865
|
+
|
|
45866
|
+
delete:
|
|
45867
|
+
x-resource-group: "publishing"
|
|
45868
|
+
operationId: deleteBlog
|
|
45869
|
+
tags: ["Blogs"]
|
|
45870
|
+
x-platforms: ["shopify"]
|
|
45871
|
+
summary: Delete a blog
|
|
45872
|
+
description: |
|
|
45873
|
+
Deletes the blog AND every article in it. The delete happens on the
|
|
45874
|
+
platform and is permanent; Zernio stores nothing to restore it from.
|
|
45875
|
+
|
|
45876
|
+
Supported on Shopify (platform `shopify`). Accounts on platforms
|
|
45877
|
+
without blogs support return 400; a blogs-capable platform that lacks
|
|
45878
|
+
this specific operation returns 405.
|
|
45879
|
+
security:
|
|
45880
|
+
- bearerAuth: []
|
|
45881
|
+
parameters:
|
|
45882
|
+
- { name: accountId, in: path, required: true, schema: { type: string }, description: 'Connected Shopify SocialAccount id.' }
|
|
45883
|
+
- { name: blogId, in: path, required: true, schema: { type: string, pattern: '^\d+$' }, description: 'Platform-native numeric blog id. Non-numeric values return 400.' }
|
|
45884
|
+
responses:
|
|
45885
|
+
'204': { description: Blog deleted (no content). }
|
|
45886
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
45887
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
45888
|
+
'403': { description: 'The platform rejected the request (code insufficient_permissions); reconnect the Shopify account to restore access.' }
|
|
45889
|
+
'404': { description: 'Account not found or not accessible (code account_not_found), or blog not found (code blog_not_found).' }
|
|
45890
|
+
'405': { description: Platform does not support deleting a blog. }
|
|
45891
|
+
'429': { description: 'Rate limited, either by Zernio or by Shopify. Retry later.' }
|
|
45892
|
+
|
|
45893
|
+
/v1/accounts/{accountId}/blogs/{blogId}/articles:
|
|
45894
|
+
get:
|
|
45895
|
+
x-resource-group: "publishing"
|
|
45896
|
+
operationId: listBlogArticles
|
|
45897
|
+
tags: ["Blogs"]
|
|
45898
|
+
x-platforms: ["shopify"]
|
|
45899
|
+
summary: List blog articles
|
|
45900
|
+
description: |
|
|
45901
|
+
Lists the articles of a blog. Cursor-paginated: pass `limit` (1-50,
|
|
45902
|
+
default 20) and the `cursor` from a previous response's `nextCursor`;
|
|
45903
|
+
`nextCursor` is null when there are no more pages.
|
|
45904
|
+
|
|
45905
|
+
Supported on Shopify (platform `shopify`). Accounts on platforms
|
|
45906
|
+
without blogs support return 400; a blogs-capable platform that lacks
|
|
45907
|
+
this specific operation returns 405.
|
|
45908
|
+
security:
|
|
45909
|
+
- bearerAuth: []
|
|
45910
|
+
parameters:
|
|
45911
|
+
- { name: accountId, in: path, required: true, schema: { type: string }, description: 'Connected Shopify SocialAccount id.' }
|
|
45912
|
+
- { name: blogId, in: path, required: true, schema: { type: string, pattern: '^\d+$' }, description: 'Platform-native numeric blog id. Non-numeric values return 400.' }
|
|
45913
|
+
- { name: limit, in: query, required: false, schema: { type: integer, minimum: 1, maximum: 50, default: 20 }, description: 'Page size (1-50).' }
|
|
45914
|
+
- { name: cursor, in: query, required: false, schema: { type: string }, description: 'Opaque cursor from a previous response. Omit for the first page.' }
|
|
45915
|
+
responses:
|
|
45916
|
+
'200':
|
|
45917
|
+
description: Articles listed
|
|
45918
|
+
content:
|
|
45919
|
+
application/json:
|
|
45920
|
+
schema:
|
|
45921
|
+
type: object
|
|
45922
|
+
properties:
|
|
45923
|
+
platform: { type: string, enum: [shopify] }
|
|
45924
|
+
articles:
|
|
45925
|
+
type: array
|
|
45926
|
+
items: { $ref: '#/components/schemas/BlogArticle' }
|
|
45927
|
+
nextCursor: { type: [string, "null"], description: 'Cursor for the next page; null when there are no more pages.' }
|
|
45928
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
45929
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
45930
|
+
'403': { description: 'The platform rejected the request (code insufficient_permissions); reconnect the Shopify account to restore access.' }
|
|
45931
|
+
'404': { description: 'Account not found or not accessible (code account_not_found), or blog not found (code blog_not_found).' }
|
|
45932
|
+
'405': { description: Platform does not support listing articles. }
|
|
45933
|
+
'429': { description: 'Rate limited, either by Zernio or by Shopify. Retry later.' }
|
|
45934
|
+
|
|
45935
|
+
post:
|
|
45936
|
+
x-resource-group: "publishing"
|
|
45937
|
+
operationId: createBlogArticle
|
|
45938
|
+
tags: ["Blogs"]
|
|
45939
|
+
x-platforms: ["shopify"]
|
|
45940
|
+
summary: Create a blog article
|
|
45941
|
+
description: |
|
|
45942
|
+
Creates an article on the blog. Publishing behavior:
|
|
45943
|
+
|
|
45944
|
+
- `isPublished: false` keeps the article as a draft.
|
|
45945
|
+
- A future `publishDate` schedules publication natively on the
|
|
45946
|
+
platform; the platform publishes it at that time with no Zernio
|
|
45947
|
+
queue involved.
|
|
45948
|
+
- `seo.title` / `seo.description` map to Shopify's global `title_tag`
|
|
45949
|
+
and `description_tag` metafields (the fields Shopify themes read for
|
|
45950
|
+
the page title and meta description).
|
|
45951
|
+
|
|
45952
|
+
Supported on Shopify (platform `shopify`). Accounts on platforms
|
|
45953
|
+
without blogs support return 400; a blogs-capable platform that lacks
|
|
45954
|
+
this specific operation returns 405.
|
|
45955
|
+
security:
|
|
45956
|
+
- bearerAuth: []
|
|
45957
|
+
parameters:
|
|
45958
|
+
- { name: accountId, in: path, required: true, schema: { type: string }, description: 'Connected Shopify SocialAccount id.' }
|
|
45959
|
+
- { name: blogId, in: path, required: true, schema: { type: string, pattern: '^\d+$' }, description: 'Platform-native numeric blog id. Non-numeric values return 400.' }
|
|
45960
|
+
requestBody:
|
|
45961
|
+
required: true
|
|
45962
|
+
content:
|
|
45963
|
+
application/json:
|
|
45964
|
+
schema:
|
|
45965
|
+
type: object
|
|
45966
|
+
required: [title]
|
|
45967
|
+
properties:
|
|
45968
|
+
title: { type: string, minLength: 1 }
|
|
45969
|
+
bodyHtml: { type: string, description: 'Article body as HTML.' }
|
|
45970
|
+
handle: { type: string, description: 'URL slug. Generated from the title when omitted.' }
|
|
45971
|
+
tags: { type: array, items: { type: string } }
|
|
45972
|
+
author: { type: string, description: 'Display name of the article author.' }
|
|
45973
|
+
excerpt: { type: string, description: 'Short summary shown in blog listings.' }
|
|
45974
|
+
image:
|
|
45975
|
+
type: object
|
|
45976
|
+
required: [url]
|
|
45977
|
+
description: 'Featured image. The platform downloads it, so the URL must be publicly reachable.'
|
|
45978
|
+
properties:
|
|
45979
|
+
url: { type: string, format: uri }
|
|
45980
|
+
altText: { type: string }
|
|
45981
|
+
seo:
|
|
45982
|
+
type: object
|
|
45983
|
+
description: 'Search-engine overrides. Maps to Shopify global metafields (title_tag and description_tag).'
|
|
45984
|
+
properties:
|
|
45985
|
+
title: { type: string }
|
|
45986
|
+
description: { type: string }
|
|
45987
|
+
isPublished: { type: boolean, description: 'Set false to create the article as a draft.' }
|
|
45988
|
+
publishDate: { type: string, format: date-time, description: 'ISO 8601 datetime with offset (or Z). A future date schedules publication natively on the platform.' }
|
|
45989
|
+
responses:
|
|
45990
|
+
'201':
|
|
45991
|
+
description: Article created
|
|
45992
|
+
content:
|
|
45993
|
+
application/json:
|
|
45994
|
+
schema:
|
|
45995
|
+
type: object
|
|
45996
|
+
properties:
|
|
45997
|
+
platform: { type: string, enum: [shopify] }
|
|
45998
|
+
article: { $ref: '#/components/schemas/BlogArticle' }
|
|
45999
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
46000
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
46001
|
+
'403': { description: 'The platform rejected the request (code insufficient_permissions); reconnect the Shopify account to restore access.' }
|
|
46002
|
+
'404': { description: 'Account not found or not accessible (code account_not_found), or blog not found (code blog_not_found).' }
|
|
46003
|
+
'405': { description: Platform does not support creating articles. }
|
|
46004
|
+
'429': { description: 'Rate limited, either by Zernio or by Shopify. Retry later.' }
|
|
46005
|
+
|
|
46006
|
+
/v1/accounts/{accountId}/blogs/{blogId}/articles/{articleId}:
|
|
46007
|
+
get:
|
|
46008
|
+
x-resource-group: "publishing"
|
|
46009
|
+
operationId: getBlogArticle
|
|
46010
|
+
tags: ["Blogs"]
|
|
46011
|
+
x-platforms: ["shopify"]
|
|
46012
|
+
summary: Get a blog article
|
|
46013
|
+
description: |
|
|
46014
|
+
Fetches a single article. An article addressed through a blog it does
|
|
46015
|
+
not belong to is a 404 (code blog_article_not_found).
|
|
46016
|
+
|
|
46017
|
+
Supported on Shopify (platform `shopify`). Accounts on platforms
|
|
46018
|
+
without blogs support return 400; a blogs-capable platform that lacks
|
|
46019
|
+
this specific operation returns 405.
|
|
46020
|
+
security:
|
|
46021
|
+
- bearerAuth: []
|
|
46022
|
+
parameters:
|
|
46023
|
+
- { name: accountId, in: path, required: true, schema: { type: string }, description: 'Connected Shopify SocialAccount id.' }
|
|
46024
|
+
- { name: blogId, in: path, required: true, schema: { type: string, pattern: '^\d+$' }, description: 'Platform-native numeric blog id. Non-numeric values return 400.' }
|
|
46025
|
+
- { name: articleId, in: path, required: true, schema: { type: string, pattern: '^\d+$' }, description: 'Platform-native numeric article id. Non-numeric values return 400.' }
|
|
46026
|
+
responses:
|
|
46027
|
+
'200':
|
|
46028
|
+
description: Article fetched
|
|
46029
|
+
content:
|
|
46030
|
+
application/json:
|
|
46031
|
+
schema:
|
|
46032
|
+
type: object
|
|
46033
|
+
properties:
|
|
46034
|
+
platform: { type: string, enum: [shopify] }
|
|
46035
|
+
article: { $ref: '#/components/schemas/BlogArticle' }
|
|
46036
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
46037
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
46038
|
+
'403': { description: 'The platform rejected the request (code insufficient_permissions); reconnect the Shopify account to restore access.' }
|
|
46039
|
+
'404': { description: 'Account not found or not accessible (code account_not_found), blog not found (code blog_not_found), or article not found (code blog_article_not_found).' }
|
|
46040
|
+
'405': { description: Platform does not support fetching an article. }
|
|
46041
|
+
'429': { description: 'Rate limited, either by Zernio or by Shopify. Retry later.' }
|
|
46042
|
+
|
|
46043
|
+
patch:
|
|
46044
|
+
x-resource-group: "publishing"
|
|
46045
|
+
operationId: updateBlogArticle
|
|
46046
|
+
tags: ["Blogs"]
|
|
46047
|
+
x-platforms: ["shopify"]
|
|
46048
|
+
summary: Update a blog article
|
|
46049
|
+
description: |
|
|
46050
|
+
Partial-updates an article. Send any subset of the create fields
|
|
46051
|
+
(`title`, `bodyHtml`, `handle`, `tags`, `author`, `excerpt`, `image`,
|
|
46052
|
+
`seo`, `isPublished`, `publishDate`); at least one field is required
|
|
46053
|
+
(an empty body returns 400). `isPublished` and `publishDate` behave as
|
|
46054
|
+
on create: `isPublished: false` unpublishes back to a draft and a
|
|
46055
|
+
future `publishDate` schedules publication natively on the platform.
|
|
46056
|
+
|
|
46057
|
+
Supported on Shopify (platform `shopify`). Accounts on platforms
|
|
46058
|
+
without blogs support return 400; a blogs-capable platform that lacks
|
|
46059
|
+
this specific operation returns 405.
|
|
46060
|
+
security:
|
|
46061
|
+
- bearerAuth: []
|
|
46062
|
+
parameters:
|
|
46063
|
+
- { name: accountId, in: path, required: true, schema: { type: string }, description: 'Connected Shopify SocialAccount id.' }
|
|
46064
|
+
- { name: blogId, in: path, required: true, schema: { type: string, pattern: '^\d+$' }, description: 'Platform-native numeric blog id. Non-numeric values return 400.' }
|
|
46065
|
+
- { name: articleId, in: path, required: true, schema: { type: string, pattern: '^\d+$' }, description: 'Platform-native numeric article id. Non-numeric values return 400.' }
|
|
46066
|
+
requestBody:
|
|
46067
|
+
required: true
|
|
46068
|
+
content:
|
|
46069
|
+
application/json:
|
|
46070
|
+
schema:
|
|
46071
|
+
type: object
|
|
46072
|
+
description: 'At least one field is required.'
|
|
46073
|
+
properties:
|
|
46074
|
+
title: { type: string, minLength: 1 }
|
|
46075
|
+
bodyHtml: { type: string, description: 'Article body as HTML.' }
|
|
46076
|
+
handle: { type: string, description: 'URL slug of the article.' }
|
|
46077
|
+
tags: { type: array, items: { type: string }, description: 'Replaces the full tag list.' }
|
|
46078
|
+
author: { type: string, description: 'Display name of the article author.' }
|
|
46079
|
+
excerpt: { type: string, description: 'Short summary shown in blog listings.' }
|
|
46080
|
+
image:
|
|
46081
|
+
type: object
|
|
46082
|
+
required: [url]
|
|
46083
|
+
description: 'Featured image. The platform downloads it, so the URL must be publicly reachable.'
|
|
46084
|
+
properties:
|
|
46085
|
+
url: { type: string, format: uri }
|
|
46086
|
+
altText: { type: string }
|
|
46087
|
+
seo:
|
|
46088
|
+
type: object
|
|
46089
|
+
description: 'Search-engine overrides. Maps to Shopify global metafields (title_tag and description_tag).'
|
|
46090
|
+
properties:
|
|
46091
|
+
title: { type: string }
|
|
46092
|
+
description: { type: string }
|
|
46093
|
+
isPublished: { type: boolean, description: 'Set false to unpublish the article back to a draft.' }
|
|
46094
|
+
publishDate: { type: string, format: date-time, description: 'ISO 8601 datetime with offset (or Z). A future date schedules publication natively on the platform.' }
|
|
46095
|
+
responses:
|
|
46096
|
+
'200':
|
|
46097
|
+
description: Article updated
|
|
46098
|
+
content:
|
|
46099
|
+
application/json:
|
|
46100
|
+
schema:
|
|
46101
|
+
type: object
|
|
46102
|
+
properties:
|
|
46103
|
+
platform: { type: string, enum: [shopify] }
|
|
46104
|
+
article: { $ref: '#/components/schemas/BlogArticle' }
|
|
46105
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
46106
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
46107
|
+
'403': { description: 'The platform rejected the request (code insufficient_permissions); reconnect the Shopify account to restore access.' }
|
|
46108
|
+
'404': { description: 'Account not found or not accessible (code account_not_found), blog not found (code blog_not_found), or article not found (code blog_article_not_found).' }
|
|
46109
|
+
'405': { description: Platform does not support updating an article. }
|
|
46110
|
+
'429': { description: 'Rate limited, either by Zernio or by Shopify. Retry later.' }
|
|
46111
|
+
|
|
46112
|
+
delete:
|
|
46113
|
+
x-resource-group: "publishing"
|
|
46114
|
+
operationId: deleteBlogArticle
|
|
46115
|
+
tags: ["Blogs"]
|
|
46116
|
+
x-platforms: ["shopify"]
|
|
46117
|
+
summary: Delete a blog article
|
|
46118
|
+
description: |
|
|
46119
|
+
Deletes the article. The delete happens on the platform and is
|
|
46120
|
+
permanent; Zernio stores nothing to restore it from.
|
|
46121
|
+
|
|
46122
|
+
Supported on Shopify (platform `shopify`). Accounts on platforms
|
|
46123
|
+
without blogs support return 400; a blogs-capable platform that lacks
|
|
46124
|
+
this specific operation returns 405.
|
|
46125
|
+
security:
|
|
46126
|
+
- bearerAuth: []
|
|
46127
|
+
parameters:
|
|
46128
|
+
- { name: accountId, in: path, required: true, schema: { type: string }, description: 'Connected Shopify SocialAccount id.' }
|
|
46129
|
+
- { name: blogId, in: path, required: true, schema: { type: string, pattern: '^\d+$' }, description: 'Platform-native numeric blog id. Non-numeric values return 400.' }
|
|
46130
|
+
- { name: articleId, in: path, required: true, schema: { type: string, pattern: '^\d+$' }, description: 'Platform-native numeric article id. Non-numeric values return 400.' }
|
|
46131
|
+
responses:
|
|
46132
|
+
'204': { description: Article deleted (no content). }
|
|
46133
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
46134
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
46135
|
+
'403': { description: 'The platform rejected the request (code insufficient_permissions); reconnect the Shopify account to restore access.' }
|
|
46136
|
+
'404': { description: 'Account not found or not accessible (code account_not_found), blog not found (code blog_not_found), or article not found (code blog_article_not_found).' }
|
|
46137
|
+
'405': { description: Platform does not support deleting an article. }
|
|
46138
|
+
'429': { description: 'Rate limited, either by Zernio or by Shopify. Retry later.' }
|
|
44348
46139
|
|
|
44349
46140
|
/v1/verify/verifications:
|
|
44350
46141
|
post:
|