zernio-sdk 0.0.821 → 0.0.823
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 +7 -0
- data/docs/AnalyticsApi.md +78 -0
- data/docs/AnalyticsDeltaEntry.md +34 -0
- data/docs/AnalyticsDeltaEntryMetrics.md +44 -0
- data/docs/AnalyticsDeltaResponse.md +22 -0
- data/docs/BoostPostRequest.md +3 -1
- data/docs/CreateCallAdRequest.md +3 -1
- data/docs/CreateMessagingAdRequest.md +3 -1
- data/docs/CreateStandaloneAdRequest.md +3 -1
- data/docs/CtwaAdRequestBody.md +4 -2
- data/docs/WebhookEventsApi.md +69 -0
- data/docs/WebhookPayloadAnalyticsSynced.md +26 -0
- data/docs/WebhookPayloadAnalyticsSyncedAccount.md +24 -0
- data/docs/WebhookPayloadAnalyticsSyncedSync.md +20 -0
- data/lib/zernio-sdk/api/analytics_api.rb +77 -0
- data/lib/zernio-sdk/api/webhook_events_api.rb +66 -0
- data/lib/zernio-sdk/models/analytics_delta_entry.rb +380 -0
- data/lib/zernio-sdk/models/analytics_delta_entry_metrics.rb +507 -0
- data/lib/zernio-sdk/models/analytics_delta_response.rb +221 -0
- data/lib/zernio-sdk/models/boost_post_request.rb +14 -2
- data/lib/zernio-sdk/models/create_call_ad_request.rb +14 -2
- data/lib/zernio-sdk/models/create_messaging_ad_request.rb +14 -2
- data/lib/zernio-sdk/models/create_standalone_ad_request.rb +14 -2
- data/lib/zernio-sdk/models/ctwa_ad_request_body.rb +17 -5
- data/lib/zernio-sdk/models/webhook_payload_analytics_synced.rb +295 -0
- data/lib/zernio-sdk/models/webhook_payload_analytics_synced_account.rb +244 -0
- data/lib/zernio-sdk/models/webhook_payload_analytics_synced_sync.rb +193 -0
- data/lib/zernio-sdk/version.rb +1 -1
- data/lib/zernio-sdk.rb +6 -0
- data/openapi.yaml +392 -10
- data/spec/api/analytics_api_spec.rb +15 -0
- data/spec/models/analytics_delta_entry_metrics_spec.rb +114 -0
- data/spec/models/analytics_delta_entry_spec.rb +84 -0
- data/spec/models/analytics_delta_response_spec.rb +48 -0
- data/spec/models/boost_post_request_spec.rb +6 -0
- data/spec/models/create_call_ad_request_spec.rb +6 -0
- data/spec/models/create_messaging_ad_request_spec.rb +6 -0
- data/spec/models/create_standalone_ad_request_spec.rb +6 -0
- data/spec/models/create_webhook_settings_request_spec.rb +1 -1
- data/spec/models/ctwa_ad_request_body_spec.rb +6 -0
- data/spec/models/update_webhook_settings_request_spec.rb +1 -1
- data/spec/models/webhook_payload_analytics_synced_account_spec.rb +54 -0
- data/spec/models/webhook_payload_analytics_synced_spec.rb +64 -0
- data/spec/models/webhook_payload_analytics_synced_sync_spec.rb +42 -0
- data/spec/models/webhook_spec.rb +1 -1
- metadata +1773 -1749
data/openapi.yaml
CHANGED
|
@@ -159,6 +159,7 @@ x-documentation:
|
|
|
159
159
|
- `account.connected` - Social account connected
|
|
160
160
|
- `account.disconnected` - Social account disconnected (token expired)
|
|
161
161
|
- `account.ads.initial_sync_completed` - Initial ads sync (discovery + 90-day backfill) completed for an ads-enabled account
|
|
162
|
+
- `analytics.synced` - One connected account's analytics sync cycle finished. A trigger, not a transport: it carries no metrics and no cursor, so call `GET /v1/analytics/delta` with your own last `nextCursor` to read what changed across every account. Poll-driven (~hourly per account), not real-time. High volume: subscribe to it on a dedicated endpoint.
|
|
162
163
|
- `message.received` - New inbound DM or SMS received (SMS arrives with `platform: "sms"`)
|
|
163
164
|
- `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
|
|
164
165
|
- `message.sent` - DM sent via the API
|
|
@@ -431,10 +432,10 @@ tags:
|
|
|
431
432
|
- name: Webhooks
|
|
432
433
|
description: |
|
|
433
434
|
Configure webhooks for real-time notifications. Webhooks can be created from the dashboard (Settings → Webhooks) or via this API.
|
|
434
|
-
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.account.name_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, phone_number.stock_available, verification.approved, verification.failed, webhook.test.
|
|
435
|
+
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, analytics.synced, 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.account.name_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, phone_number.stock_available, verification.approved, verification.failed, webhook.test.
|
|
435
436
|
Security: optional HMAC-SHA256 signature in X-Zernio-Signature header. Configure a secret key to enable verification. Custom headers supported.
|
|
436
437
|
|
|
437
|
-
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.*, whatsapp.template.* and whatsapp.account.* 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.
|
|
438
|
+
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.*, whatsapp.template.* and whatsapp.account.* to accounts, analytics.* to analytics, 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.
|
|
438
439
|
- name: Webhook Events
|
|
439
440
|
description: |
|
|
440
441
|
Incoming webhook deliveries sent by Zernio to your configured endpoint URL.
|
|
@@ -1176,8 +1177,23 @@ components:
|
|
|
1176
1177
|
a default payor.
|
|
1177
1178
|
regionalRegulatedCategories:
|
|
1178
1179
|
type: array
|
|
1179
|
-
description: 'Meta only. Regional regulation categories required when the ad set targets certain countries (e.g. SINGAPORE_UNIVERSAL, TAIWAN_UNIVERSAL, THAILAND_UNIVERSAL, AUSTRALIA_FINSERV, INDIA_FINSERV). Forwarded to the ad set.'
|
|
1180
|
+
description: 'Meta only. Regional regulation categories required when the ad set targets certain countries (e.g. BRAZIL_REGULATION, SINGAPORE_UNIVERSAL, TAIWAN_UNIVERSAL, THAILAND_UNIVERSAL, AUSTRALIA_FINSERV, INDIA_FINSERV, TAIWAN_FINSERV). Forwarded to the ad set.'
|
|
1180
1181
|
items: { type: string }
|
|
1182
|
+
regionalRegulationIdentities:
|
|
1183
|
+
type: object
|
|
1184
|
+
additionalProperties: { type: integer }
|
|
1185
|
+
description: |
|
|
1186
|
+
Meta only. Beneficiary/payer entity IDs required alongside regionalRegulatedCategories.
|
|
1187
|
+
Values are numeric IDs from the advertiser's Meta verification/authorization setup.
|
|
1188
|
+
Keys depend on the declared category: BRAZIL_REGULATION and THAILAND_UNIVERSAL use
|
|
1189
|
+
universal_beneficiary / universal_payer; SINGAPORE_UNIVERSAL uses
|
|
1190
|
+
singapore_universal_beneficiary / singapore_universal_payer; TAIWAN_UNIVERSAL uses
|
|
1191
|
+
taiwan_universal_beneficiary / taiwan_universal_payer; TAIWAN_FINSERV uses
|
|
1192
|
+
taiwan_finserv_beneficiary / taiwan_finserv_payer; AUSTRALIA_FINSERV uses
|
|
1193
|
+
australia_finserv_beneficiary / australia_finserv_payer; INDIA_FINSERV uses
|
|
1194
|
+
india_finserv_beneficiary / india_finserv_payer.
|
|
1195
|
+
Both beneficiary and payer must be included. If omitted and the advertiser has
|
|
1196
|
+
set defaults in Meta Ads Manager advertising settings, Meta auto-fills them.
|
|
1181
1197
|
WorkflowNode:
|
|
1182
1198
|
type: object
|
|
1183
1199
|
required: [id, type]
|
|
@@ -2435,7 +2451,7 @@ components:
|
|
|
2435
2451
|
type: array
|
|
2436
2452
|
items:
|
|
2437
2453
|
type: string
|
|
2438
|
-
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.account.name_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, phone_number.stock_available, verification.approved, verification.failed]
|
|
2454
|
+
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, analytics.synced, 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.account.name_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, phone_number.stock_available, verification.approved, verification.failed]
|
|
2439
2455
|
description: Events subscribed to
|
|
2440
2456
|
isActive:
|
|
2441
2457
|
type: boolean
|
|
@@ -2877,6 +2893,80 @@ components:
|
|
|
2877
2893
|
type: string
|
|
2878
2894
|
format: date-time
|
|
2879
2895
|
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.'
|
|
2896
|
+
WebhookPayloadAnalyticsSynced:
|
|
2897
|
+
type: object
|
|
2898
|
+
description: |
|
|
2899
|
+
Webhook payload for `analytics.synced`. Fired once per connected account each
|
|
2900
|
+
time its analytics sync cycle completes successfully. Poll-driven (roughly
|
|
2901
|
+
hourly per account), not real-time, and never fired for a skipped or failed
|
|
2902
|
+
cycle.
|
|
2903
|
+
|
|
2904
|
+
A TRIGGER, not a transport: it deliberately carries no metrics and no cursor.
|
|
2905
|
+
When it arrives, call `GET /v1/analytics/delta` with YOUR OWN last `nextCursor`
|
|
2906
|
+
to read what changed, across every account, in one paginated stream.
|
|
2907
|
+
|
|
2908
|
+
The absent cursor is deliberate. The feed's ordering position is assigned inside
|
|
2909
|
+
the analytics store when the row is materialized, which normally has not
|
|
2910
|
+
happened yet at the moment this event fires, so a cursor minted here could sit
|
|
2911
|
+
ahead of the very rows the event announces and make you skip them. Your own
|
|
2912
|
+
`nextCursor` is always in the feed's own ordering and can never do that.
|
|
2913
|
+
|
|
2914
|
+
Because of that same lag, a delta read issued the instant this event lands can
|
|
2915
|
+
legitimately come back empty. That is not "nothing changed": poll again with the
|
|
2916
|
+
same cursor you just used rather than treating the account as done.
|
|
2917
|
+
|
|
2918
|
+
Subscribe to this event on a DEDICATED webhook endpoint. It is high volume
|
|
2919
|
+
(roughly one delivery per connected account per hour) and a subscription's
|
|
2920
|
+
consecutive-failure count is shared across all of its events, so an outage while
|
|
2921
|
+
this event is flowing can suppress the low-volume publishing events that share
|
|
2922
|
+
the same subscription.
|
|
2923
|
+
required: [id, event, account, sync, timestamp]
|
|
2924
|
+
properties:
|
|
2925
|
+
id:
|
|
2926
|
+
type: string
|
|
2927
|
+
description: Stable webhook event ID
|
|
2928
|
+
event:
|
|
2929
|
+
type: string
|
|
2930
|
+
enum: [analytics.synced]
|
|
2931
|
+
account:
|
|
2932
|
+
type: object
|
|
2933
|
+
required: [accountId, profileId, platform, username]
|
|
2934
|
+
properties:
|
|
2935
|
+
accountId:
|
|
2936
|
+
type: string
|
|
2937
|
+
description: 'The account''s unique identifier (same as used in /v1/accounts/{accountId})'
|
|
2938
|
+
profileId:
|
|
2939
|
+
type: string
|
|
2940
|
+
description: The profile this account belongs to
|
|
2941
|
+
platform:
|
|
2942
|
+
type: string
|
|
2943
|
+
example: youtube
|
|
2944
|
+
username:
|
|
2945
|
+
type: string
|
|
2946
|
+
sync:
|
|
2947
|
+
type: object
|
|
2948
|
+
description: Summary of the analytics sync cycle that just completed.
|
|
2949
|
+
required: [syncedAt, postsUpdated]
|
|
2950
|
+
properties:
|
|
2951
|
+
syncedAt:
|
|
2952
|
+
type: string
|
|
2953
|
+
format: date-time
|
|
2954
|
+
description: |
|
|
2955
|
+
When the cycle COMPLETED. Not a join key for the delta feed: the rows a
|
|
2956
|
+
cycle produces carry a `syncedAt` stamped when the cycle STARTED, which
|
|
2957
|
+
is measured at around one second earlier at the median and up to a
|
|
2958
|
+
couple of minutes earlier in the tail. Correlate on `account.accountId`.
|
|
2959
|
+
postsUpdated:
|
|
2960
|
+
type: integer
|
|
2961
|
+
description: |
|
|
2962
|
+
Post records created or modified by this cycle. Not the number of delta
|
|
2963
|
+
feed rows the cycle produced, which the syncer does not report, so a
|
|
2964
|
+
cycle with a non-zero `postsUpdated` can still yield an empty delta page.
|
|
2965
|
+
example: 42
|
|
2966
|
+
timestamp:
|
|
2967
|
+
type: string
|
|
2968
|
+
format: date-time
|
|
2969
|
+
description: 'UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued).'
|
|
2880
2970
|
WebhookPayloadComment:
|
|
2881
2971
|
type: object
|
|
2882
2972
|
description: Webhook payload for comment received events (Instagram, Facebook, Twitter/X, YouTube, LinkedIn, Bluesky, Reddit)
|
|
@@ -7521,6 +7611,89 @@ components:
|
|
|
7521
7611
|
hasAnalyticsAccess:
|
|
7522
7612
|
type: boolean
|
|
7523
7613
|
description: Whether user has analytics add-on access
|
|
7614
|
+
AnalyticsDeltaEntry:
|
|
7615
|
+
type: object
|
|
7616
|
+
description: |
|
|
7617
|
+
One changed analytics snapshot. Metrics are the absolute values recorded at
|
|
7618
|
+
`syncedAt`, not the amount they moved by since the previous snapshot, so a later
|
|
7619
|
+
entry for the same `postId` always supersedes an earlier one.
|
|
7620
|
+
required: [postId, accountId, profileId, platform, platformPostId, publishedAt, syncedAt, isDeleted, metrics]
|
|
7621
|
+
properties:
|
|
7622
|
+
postId:
|
|
7623
|
+
type: string
|
|
7624
|
+
description: 'External post ID. The same identifier as `posts[]._id` in GET /v1/analytics.'
|
|
7625
|
+
accountId:
|
|
7626
|
+
type: string
|
|
7627
|
+
description: Social account this post was published through
|
|
7628
|
+
profileId:
|
|
7629
|
+
type: string
|
|
7630
|
+
description: Profile the account belongs to
|
|
7631
|
+
platform:
|
|
7632
|
+
type: string
|
|
7633
|
+
example: youtube
|
|
7634
|
+
platformPostId:
|
|
7635
|
+
type: string
|
|
7636
|
+
description: 'Platform-side post ID (for example the YouTube video ID)'
|
|
7637
|
+
publishedAt:
|
|
7638
|
+
type: string
|
|
7639
|
+
format: date-time
|
|
7640
|
+
description: 'When the post was published, ISO-8601 UTC'
|
|
7641
|
+
syncedAt:
|
|
7642
|
+
type: string
|
|
7643
|
+
format: date-time
|
|
7644
|
+
description: |
|
|
7645
|
+
When the sync cycle that produced this snapshot STARTED, ISO-8601 UTC. This
|
|
7646
|
+
is NOT the order entries arrive in and it is not a resume point: a slow cycle
|
|
7647
|
+
writes its rows after a faster cycle that started later, so `syncedAt` can go
|
|
7648
|
+
backwards between consecutive entries. Use `nextCursor` to resume.
|
|
7649
|
+
isDeleted:
|
|
7650
|
+
type: boolean
|
|
7651
|
+
description: 'True when the post was detected as deleted on the platform at this sync'
|
|
7652
|
+
metrics:
|
|
7653
|
+
type: object
|
|
7654
|
+
description: 'Metrics a platform does not report are 0, not absent.'
|
|
7655
|
+
required: [impressions, reach, likes, comments, shares, saves, sends, clicks, views, follows, igReelsAvgWatchTime, igReelsVideoViewTotalTime, reposts, reelsSkipRate]
|
|
7656
|
+
properties:
|
|
7657
|
+
impressions: { type: integer }
|
|
7658
|
+
reach: { type: integer }
|
|
7659
|
+
likes: { type: integer }
|
|
7660
|
+
comments: { type: integer }
|
|
7661
|
+
shares: { type: integer }
|
|
7662
|
+
saves: { type: integer }
|
|
7663
|
+
sends: { type: integer }
|
|
7664
|
+
clicks: { type: integer }
|
|
7665
|
+
views: { type: integer }
|
|
7666
|
+
follows: { type: integer, description: 'Follows attributed to this post (Instagram)' }
|
|
7667
|
+
igReelsAvgWatchTime: { type: integer, description: 'Instagram Reels average watch time, in milliseconds' }
|
|
7668
|
+
igReelsVideoViewTotalTime: { type: integer, description: 'Instagram Reels total watch time, in milliseconds' }
|
|
7669
|
+
reposts: { type: integer }
|
|
7670
|
+
reelsSkipRate: { type: number, description: 'Instagram Reels skip rate, 0 to 1' }
|
|
7671
|
+
AnalyticsDeltaResponse:
|
|
7672
|
+
type: object
|
|
7673
|
+
required: [data, nextCursor, hasMore]
|
|
7674
|
+
properties:
|
|
7675
|
+
data:
|
|
7676
|
+
type: array
|
|
7677
|
+
description: |
|
|
7678
|
+
Changed snapshots, oldest first, in the order the feed received them. Empty on
|
|
7679
|
+
the bootstrap call (no `cursor` supplied) and whenever nothing has changed
|
|
7680
|
+
since your cursor.
|
|
7681
|
+
items:
|
|
7682
|
+
$ref: '#/components/schemas/AnalyticsDeltaEntry'
|
|
7683
|
+
nextCursor:
|
|
7684
|
+
type: string
|
|
7685
|
+
description: |
|
|
7686
|
+
Cursor to send on the next call. ALWAYS present, including on an empty page,
|
|
7687
|
+
so you always have something to advance with, and it never moves backwards.
|
|
7688
|
+
Opaque: pass it back verbatim, and do not parse, construct or compare cursors.
|
|
7689
|
+
example: v1.WyIyMDI2LTA5LTAxIDE3OjEyOjA0IiwiNjVmMWMwYTllMmI1YWYwMDEyYWIzNGNkIl0
|
|
7690
|
+
hasMore:
|
|
7691
|
+
type: boolean
|
|
7692
|
+
description: |
|
|
7693
|
+
True when more changes are already waiting past `nextCursor`, so call again
|
|
7694
|
+
immediately. False means you are caught up: keep `nextCursor` and poll again
|
|
7695
|
+
later. This feed never ends, so `hasMore: false` does NOT mean `nextCursor`
|
|
7696
|
+
is null.
|
|
7524
7697
|
# LinkedIn Aggregate Analytics Responses
|
|
7525
7698
|
LinkedInAggregateAnalyticsTotalResponse:
|
|
7526
7699
|
type: object
|
|
@@ -9426,6 +9599,38 @@ webhooks:
|
|
|
9426
9599
|
responses:
|
|
9427
9600
|
'200':
|
|
9428
9601
|
description: Webhook received successfully
|
|
9602
|
+
analytics.synced:
|
|
9603
|
+
post:
|
|
9604
|
+
operationId: onAnalyticsSynced
|
|
9605
|
+
summary: Analytics synced event
|
|
9606
|
+
description: |
|
|
9607
|
+
Fired once per connected account each time its analytics sync cycle completes
|
|
9608
|
+
successfully. Poll-driven (roughly hourly per account), not real-time, and never
|
|
9609
|
+
fired for a skipped or failed cycle.
|
|
9610
|
+
|
|
9611
|
+
A trigger, not a transport: the payload carries no metrics and no cursor. On
|
|
9612
|
+
receipt, call `GET /v1/analytics/delta` with your own last `nextCursor` to read
|
|
9613
|
+
every post whose analytics changed, across every account, in one paginated
|
|
9614
|
+
stream instead of polling analytics once per account.
|
|
9615
|
+
|
|
9616
|
+
The feed holds back its most recent few seconds of writes, so a read issued the
|
|
9617
|
+
instant this event lands often returns an empty page for that account. Poll again
|
|
9618
|
+
with the same cursor rather than reading an empty page as "nothing changed".
|
|
9619
|
+
|
|
9620
|
+
High volume (roughly one delivery per connected account per hour). Subscribe to
|
|
9621
|
+
it on a dedicated webhook endpoint: a subscription's consecutive-failure count is
|
|
9622
|
+
shared across all of its events, so an outage while this event is flowing can
|
|
9623
|
+
suppress the low-volume publishing events on the same subscription.
|
|
9624
|
+
tags: [Webhook Events]
|
|
9625
|
+
requestBody:
|
|
9626
|
+
required: true
|
|
9627
|
+
content:
|
|
9628
|
+
application/json:
|
|
9629
|
+
schema:
|
|
9630
|
+
$ref: '#/components/schemas/WebhookPayloadAnalyticsSynced'
|
|
9631
|
+
responses:
|
|
9632
|
+
'200':
|
|
9633
|
+
description: Webhook received successfully
|
|
9429
9634
|
message.received:
|
|
9430
9635
|
post:
|
|
9431
9636
|
operationId: onMessageReceived
|
|
@@ -10909,6 +11114,171 @@ paths:
|
|
|
10909
11114
|
schema:
|
|
10910
11115
|
$ref: '#/components/schemas/ErrorResponse'
|
|
10911
11116
|
|
|
11117
|
+
/v1/analytics/delta:
|
|
11118
|
+
get:
|
|
11119
|
+
x-resource-group: "analytics"
|
|
11120
|
+
operationId: getAnalyticsDelta
|
|
11121
|
+
tags: [Analytics]
|
|
11122
|
+
summary: Analytics changed since a cursor
|
|
11123
|
+
description: |
|
|
11124
|
+
Cursor feed of the analytics snapshots that CHANGED, across every account you can
|
|
11125
|
+
read, in one paginated stream. Built for integrations that would otherwise call
|
|
11126
|
+
`GET /v1/analytics` once per connected account. Each page carries changes from
|
|
11127
|
+
many accounts at once, so your call count scales with how much actually changed
|
|
11128
|
+
rather than with how many accounts you have. Measured against a fleet of roughly
|
|
11129
|
+
1,600 connected accounts: about 1,599 per-account analytics calls an hour became
|
|
11130
|
+
about 205 delta calls an hour, a 7.8x reduction.
|
|
11131
|
+
|
|
11132
|
+
**Bootstrap once, then stay in sync.** Load your baseline from
|
|
11133
|
+
`GET /v1/analytics`, which is the historical endpoint. This one is a rolling
|
|
11134
|
+
7-day change log and cannot replay history. Then call this endpoint with NO
|
|
11135
|
+
`cursor`: it answers with an empty `data` array plus the feed's current position
|
|
11136
|
+
in `nextCursor`. Send that `nextCursor` back on the next call and you receive
|
|
11137
|
+
everything written since. `nextCursor` is present on every response, empty pages
|
|
11138
|
+
included, so you always have something to advance with.
|
|
11139
|
+
|
|
11140
|
+
**Ordering.** Entries come back oldest first, in the order the feed received
|
|
11141
|
+
them. That order is NOT `syncedAt`: `syncedAt` is stamped when an account's sync
|
|
11142
|
+
cycle started, and a slow cycle writes its rows after a faster cycle that started
|
|
11143
|
+
later, so `syncedAt` can go backwards between consecutive entries. Do not sort,
|
|
11144
|
+
filter or resume on it. The cursor is the only stable position, and it is opaque:
|
|
11145
|
+
pass it back verbatim, and do not parse, construct or compare cursors.
|
|
11146
|
+
|
|
11147
|
+
**`hasMore: false` does not mean the feed ended.** This stream has no end and
|
|
11148
|
+
`nextCursor` is never null. `hasMore: true` means more changes are already
|
|
11149
|
+
waiting, so call again straight away. `hasMore: false` means you are caught up:
|
|
11150
|
+
keep the cursor and poll again on your normal interval.
|
|
11151
|
+
|
|
11152
|
+
**The newest changes settle before they are served.** The feed deliberately holds
|
|
11153
|
+
back its last few seconds of writes, so that a row can never become visible
|
|
11154
|
+
behind a cursor you have already advanced past. A read issued the instant an
|
|
11155
|
+
`analytics.synced` webhook lands will therefore often return an empty page for
|
|
11156
|
+
that account. Do not read an empty page as "nothing changed": poll again with the
|
|
11157
|
+
SAME cursor you just used rather than advancing.
|
|
11158
|
+
|
|
11159
|
+
**Repeats inside one instant.** A sync cycle occasionally records the same post
|
|
11160
|
+
twice at the same feed position. When that happens the feed delivers one of those
|
|
11161
|
+
rows, not both. Measured over a day of production traffic, about 1.3% of rows
|
|
11162
|
+
fall in such a group and 99.4% of those groups are identical rows, so this is far
|
|
11163
|
+
more often deduplication than loss. Metrics are absolute values rather than
|
|
11164
|
+
increments, so a later entry for the same post supersedes an earlier one.
|
|
11165
|
+
|
|
11166
|
+
**Retention is 7 days.** Changes older than that leave the feed. A cursor older
|
|
11167
|
+
than 6 days is rejected with a `400` (a day of margin, because expiry is lazy).
|
|
11168
|
+
Recover by re-bootstrapping from `GET /v1/analytics` and taking a fresh cursor
|
|
11169
|
+
from a call to this endpoint with no `cursor`. A consumer that polls at least
|
|
11170
|
+
daily never reaches this.
|
|
11171
|
+
|
|
11172
|
+
Pairs with the `analytics.synced` webhook, so changes can be read on notification
|
|
11173
|
+
instead of on a timer. That event carries no cursor of its own: keep using the
|
|
11174
|
+
`nextCursor` this endpoint gave you.
|
|
11175
|
+
|
|
11176
|
+
Requires the same analytics access as `GET /v1/analytics`, and shares the
|
|
11177
|
+
stricter per-second rate-limit window applied to analytics endpoints.
|
|
11178
|
+
parameters:
|
|
11179
|
+
- name: cursor
|
|
11180
|
+
in: query
|
|
11181
|
+
schema: { type: string }
|
|
11182
|
+
description: |
|
|
11183
|
+
Opaque cursor from a previous response's `nextCursor`. Omit it to start from
|
|
11184
|
+
now: the response is then an empty page carrying the feed's current position.
|
|
11185
|
+
Rejected with a `400` when malformed, or when older than the retention window.
|
|
11186
|
+
example: v1.WyIyMDI2LTA5LTAxIDE3OjEyOjA0IiwiNjVmMWMwYTllMmI1YWYwMDEyYWIzNGNkIl0
|
|
11187
|
+
- name: limit
|
|
11188
|
+
in: query
|
|
11189
|
+
schema: { type: integer, minimum: 1, maximum: 100, default: 50 }
|
|
11190
|
+
description: 'Page size. Out-of-range values are a 400, never a silent clamp.'
|
|
11191
|
+
- name: platform
|
|
11192
|
+
in: query
|
|
11193
|
+
schema: { type: string }
|
|
11194
|
+
description: 'Filter to a single platform (for example "youtube"). Omit for every platform.'
|
|
11195
|
+
- name: profileId
|
|
11196
|
+
in: query
|
|
11197
|
+
schema: { type: string, default: all }
|
|
11198
|
+
description: 'Filter by profile ID (default "all"). Must be a valid profile ID or "all".'
|
|
11199
|
+
responses:
|
|
11200
|
+
'200':
|
|
11201
|
+
description: One page of changed analytics
|
|
11202
|
+
content:
|
|
11203
|
+
application/json:
|
|
11204
|
+
schema:
|
|
11205
|
+
$ref: '#/components/schemas/AnalyticsDeltaResponse'
|
|
11206
|
+
examples:
|
|
11207
|
+
bootstrap:
|
|
11208
|
+
summary: 'First call, no cursor: an empty page carrying the feed position'
|
|
11209
|
+
value:
|
|
11210
|
+
data: []
|
|
11211
|
+
nextCursor: "v1.WyIyMDI2LTA5LTAxIDE3OjA4OjUxIiwiIl0"
|
|
11212
|
+
hasMore: false
|
|
11213
|
+
page:
|
|
11214
|
+
summary: A page of changed snapshots
|
|
11215
|
+
value:
|
|
11216
|
+
data:
|
|
11217
|
+
- postId: "65f1c0a9e2b5af0012ab34cd"
|
|
11218
|
+
accountId: "64e1f0a9e2b5af0012ab34cd"
|
|
11219
|
+
profileId: "64e1f0a9e2b5af0012ab34aa"
|
|
11220
|
+
platform: "youtube"
|
|
11221
|
+
platformPostId: "dQw4w9WgXcQ"
|
|
11222
|
+
publishedAt: "2026-08-28T10:00:05Z"
|
|
11223
|
+
syncedAt: "2026-09-01T17:11:38Z"
|
|
11224
|
+
isDeleted: false
|
|
11225
|
+
metrics:
|
|
11226
|
+
impressions: 15420
|
|
11227
|
+
reach: 12350
|
|
11228
|
+
likes: 342
|
|
11229
|
+
comments: 28
|
|
11230
|
+
shares: 45
|
|
11231
|
+
saves: 12
|
|
11232
|
+
sends: 0
|
|
11233
|
+
clicks: 189
|
|
11234
|
+
views: 9310
|
|
11235
|
+
follows: 4
|
|
11236
|
+
igReelsAvgWatchTime: 0
|
|
11237
|
+
igReelsVideoViewTotalTime: 0
|
|
11238
|
+
reposts: 0
|
|
11239
|
+
reelsSkipRate: 0
|
|
11240
|
+
nextCursor: "v1.WyIyMDI2LTA5LTAxIDE3OjEyOjA0IiwiNjVmMWMwYTllMmI1YWYwMDEyYWIzNGNkIl0"
|
|
11241
|
+
hasMore: true
|
|
11242
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
11243
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
11244
|
+
'402':
|
|
11245
|
+
description: Analytics access required. Legacy plans need the Analytics add-on; included by default on usage-based plans.
|
|
11246
|
+
content:
|
|
11247
|
+
application/json:
|
|
11248
|
+
schema:
|
|
11249
|
+
type: object
|
|
11250
|
+
properties:
|
|
11251
|
+
error: { type: string, example: Analytics add-on required }
|
|
11252
|
+
code: { type: string, example: analytics_addon_required }
|
|
11253
|
+
'403':
|
|
11254
|
+
description: |
|
|
11255
|
+
The caller cannot read the requested profile, the API key is scoped to other
|
|
11256
|
+
profiles, or the profile sits outside the plan's profile limit (`code`
|
|
11257
|
+
`PROFILE_OVER_LIMIT`).
|
|
11258
|
+
content:
|
|
11259
|
+
application/json:
|
|
11260
|
+
schema:
|
|
11261
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
11262
|
+
'404': { $ref: '#/components/responses/NotFound' }
|
|
11263
|
+
'500':
|
|
11264
|
+
description: Internal server error
|
|
11265
|
+
content:
|
|
11266
|
+
application/json:
|
|
11267
|
+
schema:
|
|
11268
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
11269
|
+
'503':
|
|
11270
|
+
description: |
|
|
11271
|
+
The delta feed is temporarily unavailable, for example in the minutes between
|
|
11272
|
+
an application release and the analytics store catching up with it. Nothing is
|
|
11273
|
+
wrong with the request: retry it unchanged, honouring `Retry-After`. The feed
|
|
11274
|
+
answers this rather than an empty page, because an empty page is
|
|
11275
|
+
indistinguishable from "nothing changed" and would advance you past a window
|
|
11276
|
+
you never received.
|
|
11277
|
+
content:
|
|
11278
|
+
application/json:
|
|
11279
|
+
schema:
|
|
11280
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
11281
|
+
|
|
10912
11282
|
/v1/analytics/youtube/channel-insights:
|
|
10913
11283
|
get:
|
|
10914
11284
|
x-resource-group: "analytics"
|
|
@@ -25387,7 +25757,7 @@ paths:
|
|
|
25387
25757
|
minItems: 1
|
|
25388
25758
|
items:
|
|
25389
25759
|
type: string
|
|
25390
|
-
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.account.name_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, phone_number.stock_available, verification.approved, verification.failed]
|
|
25760
|
+
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, analytics.synced, 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.account.name_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, phone_number.stock_available, verification.approved, verification.failed]
|
|
25391
25761
|
description: Events to subscribe to (at least one required)
|
|
25392
25762
|
isActive:
|
|
25393
25763
|
type: boolean
|
|
@@ -25506,7 +25876,7 @@ paths:
|
|
|
25506
25876
|
minItems: 1
|
|
25507
25877
|
items:
|
|
25508
25878
|
type: string
|
|
25509
|
-
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.account.name_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, phone_number.stock_available, verification.approved, verification.failed]
|
|
25879
|
+
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, analytics.synced, 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.account.name_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, phone_number.stock_available, verification.approved, verification.failed]
|
|
25510
25880
|
description: Events to subscribe to. Must contain at least one event if provided.
|
|
25511
25881
|
isActive:
|
|
25512
25882
|
type: boolean
|
|
@@ -43965,8 +44335,12 @@ paths:
|
|
|
43965
44335
|
items: { type: string }
|
|
43966
44336
|
regionalRegulatedCategories:
|
|
43967
44337
|
type: array
|
|
43968
|
-
description: 'Meta only. Regional regulation categories required when the ad set targets certain countries (e.g. SINGAPORE_UNIVERSAL, TAIWAN_UNIVERSAL, THAILAND_UNIVERSAL, AUSTRALIA_FINSERV, INDIA_FINSERV). Forwarded to the ad set.'
|
|
44338
|
+
description: 'Meta only. Regional regulation categories required when the ad set targets certain countries (e.g. BRAZIL_REGULATION, SINGAPORE_UNIVERSAL, TAIWAN_UNIVERSAL, THAILAND_UNIVERSAL, AUSTRALIA_FINSERV, INDIA_FINSERV, TAIWAN_FINSERV). Forwarded to the ad set.'
|
|
43969
44339
|
items: { type: string }
|
|
44340
|
+
regionalRegulationIdentities:
|
|
44341
|
+
type: object
|
|
44342
|
+
additionalProperties: { type: integer }
|
|
44343
|
+
description: 'Meta only. Beneficiary/payer entity IDs for regionalRegulatedCategories. Values are numeric IDs from Meta verification. Keys vary by category (e.g. universal_beneficiary / universal_payer for BRAZIL_REGULATION and THAILAND_UNIVERSAL). If omitted, Meta uses Ads Manager defaults when configured.'
|
|
43970
44344
|
linkUrl:
|
|
43971
44345
|
type: string
|
|
43972
44346
|
format: uri
|
|
@@ -44508,10 +44882,18 @@ paths:
|
|
|
44508
44882
|
type: array
|
|
44509
44883
|
description: |
|
|
44510
44884
|
Meta only. Regional regulation categories required when the ad set targets certain countries.
|
|
44511
|
-
Known values: SINGAPORE_UNIVERSAL, TAIWAN_UNIVERSAL, THAILAND_UNIVERSAL,
|
|
44512
|
-
INDIA_FINSERV, TAIWAN_FINSERV. Meta rejects the ad set without this when
|
|
44513
|
-
includes the corresponding country.
|
|
44885
|
+
Known values: BRAZIL_REGULATION, SINGAPORE_UNIVERSAL, TAIWAN_UNIVERSAL, THAILAND_UNIVERSAL,
|
|
44886
|
+
AUSTRALIA_FINSERV, INDIA_FINSERV, TAIWAN_FINSERV. Meta rejects the ad set without this when
|
|
44887
|
+
the targeting geo includes the corresponding country.
|
|
44514
44888
|
items: { type: string }
|
|
44889
|
+
regionalRegulationIdentities:
|
|
44890
|
+
type: object
|
|
44891
|
+
additionalProperties: { type: integer }
|
|
44892
|
+
description: |
|
|
44893
|
+
Meta only. Beneficiary/payer entity IDs for regionalRegulatedCategories. Values are
|
|
44894
|
+
numeric IDs from Meta verification. Keys vary by category (e.g. universal_beneficiary /
|
|
44895
|
+
universal_payer for BRAZIL_REGULATION and THAILAND_UNIVERSAL). If omitted, Meta uses
|
|
44896
|
+
Ads Manager defaults when configured.
|
|
44515
44897
|
endDate: { type: string, format: date-time, description: Required for lifetime budgets }
|
|
44516
44898
|
startDate:
|
|
44517
44899
|
type: string
|
|
@@ -54,6 +54,21 @@ describe 'AnalyticsApi' do
|
|
|
54
54
|
end
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
+
# unit tests for get_analytics_delta
|
|
58
|
+
# Analytics changed since a cursor
|
|
59
|
+
# Cursor feed of the analytics snapshots that CHANGED, across every account you can read, in one paginated stream. Built for integrations that would otherwise call `GET /v1/analytics` once per connected account. Each page carries changes from many accounts at once, so your call count scales with how much actually changed rather than with how many accounts you have. Measured against a fleet of roughly 1,600 connected accounts: about 1,599 per-account analytics calls an hour became about 205 delta calls an hour, a 7.8x reduction. **Bootstrap once, then stay in sync.** Load your baseline from `GET /v1/analytics`, which is the historical endpoint. This one is a rolling 7-day change log and cannot replay history. Then call this endpoint with NO `cursor`: it answers with an empty `data` array plus the feed's current position in `nextCursor`. Send that `nextCursor` back on the next call and you receive everything written since. `nextCursor` is present on every response, empty pages included, so you always have something to advance with. **Ordering.** Entries come back oldest first, in the order the feed received them. That order is NOT `syncedAt`: `syncedAt` is stamped when an account's sync cycle started, and a slow cycle writes its rows after a faster cycle that started later, so `syncedAt` can go backwards between consecutive entries. Do not sort, filter or resume on it. The cursor is the only stable position, and it is opaque: pass it back verbatim, and do not parse, construct or compare cursors. **`hasMore: false` does not mean the feed ended.** This stream has no end and `nextCursor` is never null. `hasMore: true` means more changes are already waiting, so call again straight away. `hasMore: false` means you are caught up: keep the cursor and poll again on your normal interval. **The newest changes settle before they are served.** The feed deliberately holds back its last few seconds of writes, so that a row can never become visible behind a cursor you have already advanced past. A read issued the instant an `analytics.synced` webhook lands will therefore often return an empty page for that account. Do not read an empty page as \"nothing changed\": poll again with the SAME cursor you just used rather than advancing. **Repeats inside one instant.** A sync cycle occasionally records the same post twice at the same feed position. When that happens the feed delivers one of those rows, not both. Measured over a day of production traffic, about 1.3% of rows fall in such a group and 99.4% of those groups are identical rows, so this is far more often deduplication than loss. Metrics are absolute values rather than increments, so a later entry for the same post supersedes an earlier one. **Retention is 7 days.** Changes older than that leave the feed. A cursor older than 6 days is rejected with a `400` (a day of margin, because expiry is lazy). Recover by re-bootstrapping from `GET /v1/analytics` and taking a fresh cursor from a call to this endpoint with no `cursor`. A consumer that polls at least daily never reaches this. Pairs with the `analytics.synced` webhook, so changes can be read on notification instead of on a timer. That event carries no cursor of its own: keep using the `nextCursor` this endpoint gave you. Requires the same analytics access as `GET /v1/analytics`, and shares the stricter per-second rate-limit window applied to analytics endpoints.
|
|
60
|
+
# @param [Hash] opts the optional parameters
|
|
61
|
+
# @option opts [String] :cursor Opaque cursor from a previous response's `nextCursor`. Omit it to start from now: the response is then an empty page carrying the feed's current position. Rejected with a `400` when malformed, or when older than the retention window.
|
|
62
|
+
# @option opts [Integer] :limit Page size. Out-of-range values are a 400, never a silent clamp.
|
|
63
|
+
# @option opts [String] :platform Filter to a single platform (for example \"youtube\"). Omit for every platform.
|
|
64
|
+
# @option opts [String] :profile_id Filter by profile ID (default \"all\"). Must be a valid profile ID or \"all\".
|
|
65
|
+
# @return [AnalyticsDeltaResponse]
|
|
66
|
+
describe 'get_analytics_delta test' do
|
|
67
|
+
it 'should work' do
|
|
68
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
57
72
|
# unit tests for get_best_time_to_post
|
|
58
73
|
# Get best times to post
|
|
59
74
|
# Returns the best times to post based on historical engagement data. Groups all published posts by day of week and hour (UTC), calculating average engagement per slot. Use this to auto-schedule posts at optimal times. Requires the Analytics add-on.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
#Zernio API
|
|
3
|
+
|
|
4
|
+
#API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal. Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema).
|
|
5
|
+
|
|
6
|
+
The version of the OpenAPI document: 1.0.4
|
|
7
|
+
Contact: support@zernio.com
|
|
8
|
+
Generated by: https://openapi-generator.tech
|
|
9
|
+
Generator version: 7.19.0
|
|
10
|
+
|
|
11
|
+
=end
|
|
12
|
+
|
|
13
|
+
require 'spec_helper'
|
|
14
|
+
require 'json'
|
|
15
|
+
require 'date'
|
|
16
|
+
|
|
17
|
+
# Unit tests for Zernio::AnalyticsDeltaEntryMetrics
|
|
18
|
+
# Automatically generated by openapi-generator (https://openapi-generator.tech)
|
|
19
|
+
# Please update as you see appropriate
|
|
20
|
+
describe Zernio::AnalyticsDeltaEntryMetrics do
|
|
21
|
+
#let(:instance) { Zernio::AnalyticsDeltaEntryMetrics.new }
|
|
22
|
+
|
|
23
|
+
describe 'test an instance of AnalyticsDeltaEntryMetrics' do
|
|
24
|
+
it 'should create an instance of AnalyticsDeltaEntryMetrics' do
|
|
25
|
+
# uncomment below to test the instance creation
|
|
26
|
+
#expect(instance).to be_instance_of(Zernio::AnalyticsDeltaEntryMetrics)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe 'test attribute "impressions"' do
|
|
31
|
+
it 'should work' do
|
|
32
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe 'test attribute "reach"' do
|
|
37
|
+
it 'should work' do
|
|
38
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe 'test attribute "likes"' do
|
|
43
|
+
it 'should work' do
|
|
44
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe 'test attribute "comments"' do
|
|
49
|
+
it 'should work' do
|
|
50
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
describe 'test attribute "shares"' do
|
|
55
|
+
it 'should work' do
|
|
56
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe 'test attribute "saves"' do
|
|
61
|
+
it 'should work' do
|
|
62
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
describe 'test attribute "sends"' do
|
|
67
|
+
it 'should work' do
|
|
68
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
describe 'test attribute "clicks"' do
|
|
73
|
+
it 'should work' do
|
|
74
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe 'test attribute "views"' do
|
|
79
|
+
it 'should work' do
|
|
80
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
describe 'test attribute "follows"' do
|
|
85
|
+
it 'should work' do
|
|
86
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
describe 'test attribute "ig_reels_avg_watch_time"' do
|
|
91
|
+
it 'should work' do
|
|
92
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
describe 'test attribute "ig_reels_video_view_total_time"' do
|
|
97
|
+
it 'should work' do
|
|
98
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
describe 'test attribute "reposts"' do
|
|
103
|
+
it 'should work' do
|
|
104
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
describe 'test attribute "reels_skip_rate"' do
|
|
109
|
+
it 'should work' do
|
|
110
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
end
|