zernio-sdk 0.0.786 → 0.0.787

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e70db227d77b0022f2479e97c89b45ae0fafd9de3a671089251aa2aea36db7db
4
- data.tar.gz: c07a16a15d790252b2cffdffcc4e97ff13ad5ee2753cbb72d6323fbb46b498ca
3
+ metadata.gz: d30bccee7c44b7e2613311bb6f2a88f149ece5716e1023b9192803ec4abdcfe4
4
+ data.tar.gz: 19c7c6f3c402fb0734182802b0d0cc3f377e3123ccce7fcfbb3679d79e5ea7f1
5
5
  SHA512:
6
- metadata.gz: 8d341798bd632d644c9dcd9ddb3b990af1c26ac3025ed16a8727e0a1e9d03e8d31dd39eaad6ae0ad8beafdd10cc07873d3f3dc9634a27fb27cf8369d98c6ba36
7
- data.tar.gz: 1d5dd020710394301785a45933b011304dd615e43cb736404e2f071f491e046c994330fa9161bc96ff8399c53df16ee8c1e4e64b0fbfafaacc34395e929ca2c2
6
+ metadata.gz: fde8605af9ad08e7df543ddce999cd61fc97c2dbf46bbbd67ac1b27c3ebdb3f3afe9ea630c1c69d3d6379877d68b8cc4bde61fbc8993dfa921b4834db3393ccd
7
+ data.tar.gz: e768cc84bd9ec8323ca0fa974c6b58fb441d8723ae2d17e2ec23b2508e249983dee0fa9243bae92cda0100b3b9f03c553edfb1678378c93125192fb0e6aa75a0
data/README.md CHANGED
@@ -94,6 +94,7 @@ Class | Method | HTTP request | Description
94
94
  *Zernio::AccountSettingsApi* | [**set_telegram_commands**](docs/AccountSettingsApi.md#set_telegram_commands) | **PUT** /v1/accounts/{accountId}/telegram-commands | Set TG bot commands
95
95
  *Zernio::AccountsApi* | [**delete_account**](docs/AccountsApi.md#delete_account) | **DELETE** /v1/accounts/{accountId} | Disconnect account
96
96
  *Zernio::AccountsApi* | [**get_account_health**](docs/AccountsApi.md#get_account_health) | **GET** /v1/accounts/{accountId}/health | Check account health
97
+ *Zernio::AccountsApi* | [**get_account_posts**](docs/AccountsApi.md#get_account_posts) | **GET** /v1/accounts/{accountId}/posts | List posts published on the platform
97
98
  *Zernio::AccountsApi* | [**get_all_accounts_health**](docs/AccountsApi.md#get_all_accounts_health) | **GET** /v1/accounts/health | Check accounts health
98
99
  *Zernio::AccountsApi* | [**get_bluesky_settings**](docs/AccountsApi.md#get_bluesky_settings) | **GET** /v1/accounts/{accountId}/bluesky-settings | Get Bluesky account settings
99
100
  *Zernio::AccountsApi* | [**get_follower_stats**](docs/AccountsApi.md#get_follower_stats) | **GET** /v1/accounts/follower-stats | Get follower stats
@@ -1150,6 +1151,8 @@ Class | Method | HTTP request | Description
1150
1151
  - [Zernio::GetAccountHealth200ResponsePlatformConnection](docs/GetAccountHealth200ResponsePlatformConnection.md)
1151
1152
  - [Zernio::GetAccountHealth200ResponsePlatformConnectionMetaError](docs/GetAccountHealth200ResponsePlatformConnectionMetaError.md)
1152
1153
  - [Zernio::GetAccountHealth200ResponseTokenStatus](docs/GetAccountHealth200ResponseTokenStatus.md)
1154
+ - [Zernio::GetAccountPosts200Response](docs/GetAccountPosts200Response.md)
1155
+ - [Zernio::GetAccountPosts200ResponsePostsInner](docs/GetAccountPosts200ResponsePostsInner.md)
1153
1156
  - [Zernio::GetAd200Response](docs/GetAd200Response.md)
1154
1157
  - [Zernio::GetAdAccountFinance200Response](docs/GetAdAccountFinance200Response.md)
1155
1158
  - [Zernio::GetAdAccountFinance200ResponseFundingSource](docs/GetAdAccountFinance200ResponseFundingSource.md)
data/docs/AccountsApi.md CHANGED
@@ -6,6 +6,7 @@ All URIs are relative to *https://zernio.com/api*
6
6
  | ------ | ------------ | ----------- |
7
7
  | [**delete_account**](AccountsApi.md#delete_account) | **DELETE** /v1/accounts/{accountId} | Disconnect account |
8
8
  | [**get_account_health**](AccountsApi.md#get_account_health) | **GET** /v1/accounts/{accountId}/health | Check account health |
9
+ | [**get_account_posts**](AccountsApi.md#get_account_posts) | **GET** /v1/accounts/{accountId}/posts | List posts published on the platform |
9
10
  | [**get_all_accounts_health**](AccountsApi.md#get_all_accounts_health) | **GET** /v1/accounts/health | Check accounts health |
10
11
  | [**get_bluesky_settings**](AccountsApi.md#get_bluesky_settings) | **GET** /v1/accounts/{accountId}/bluesky-settings | Get Bluesky account settings |
11
12
  | [**get_follower_stats**](AccountsApi.md#get_follower_stats) | **GET** /v1/accounts/follower-stats | Get follower stats |
@@ -157,6 +158,75 @@ end
157
158
  - **Accept**: application/json
158
159
 
159
160
 
161
+ ## get_account_posts
162
+
163
+ > <GetAccountPosts200Response> get_account_posts(account_id)
164
+
165
+ List posts published on the platform
166
+
167
+ Returns the 25 most recent posts that exist on the platform for a connected account, read live from the platform API. This covers everything on the account, including posts that were never created through Zernio. Use it to obtain the platform's own post id, which the analytics endpoints take as input. On YouTube the returned `id` is the video ID that `GET /v1/analytics/youtube/daily-views`, `/video-retention` and `/demographics` expect as `videoId`, so this endpoint is what backs a video picker in your own UI. Not every field applies to every platform: `reactionCount` is Facebook and LinkedIn, `shareCount` is platform dependent, `cid` is the Bluesky content id needed to reply, and `subreddit` is Reddit only. Absent fields are omitted from the response. The account's token is refreshed before the call when it has expired. When the refresh cannot recover it, the response is a 401 with code `TOKEN_EXPIRED` and the account has to be reconnected.
168
+
169
+ ### Examples
170
+
171
+ ```ruby
172
+ require 'time'
173
+ require 'zernio-sdk'
174
+ # setup authorization
175
+ Zernio.configure do |config|
176
+ # Configure Bearer authorization (JWT): bearerAuth
177
+ config.access_token = 'YOUR_BEARER_TOKEN'
178
+ end
179
+
180
+ api_instance = Zernio::AccountsApi.new
181
+ account_id = 'account_id_example' # String |
182
+
183
+ begin
184
+ # List posts published on the platform
185
+ result = api_instance.get_account_posts(account_id)
186
+ p result
187
+ rescue Zernio::ApiError => e
188
+ puts "Error when calling AccountsApi->get_account_posts: #{e}"
189
+ end
190
+ ```
191
+
192
+ #### Using the get_account_posts_with_http_info variant
193
+
194
+ This returns an Array which contains the response data, status code and headers.
195
+
196
+ > <Array(<GetAccountPosts200Response>, Integer, Hash)> get_account_posts_with_http_info(account_id)
197
+
198
+ ```ruby
199
+ begin
200
+ # List posts published on the platform
201
+ data, status_code, headers = api_instance.get_account_posts_with_http_info(account_id)
202
+ p status_code # => 2xx
203
+ p headers # => { ... }
204
+ p data # => <GetAccountPosts200Response>
205
+ rescue Zernio::ApiError => e
206
+ puts "Error when calling AccountsApi->get_account_posts_with_http_info: #{e}"
207
+ end
208
+ ```
209
+
210
+ ### Parameters
211
+
212
+ | Name | Type | Description | Notes |
213
+ | ---- | ---- | ----------- | ----- |
214
+ | **account_id** | **String** | | |
215
+
216
+ ### Return type
217
+
218
+ [**GetAccountPosts200Response**](GetAccountPosts200Response.md)
219
+
220
+ ### Authorization
221
+
222
+ [bearerAuth](../README.md#bearerAuth)
223
+
224
+ ### HTTP request headers
225
+
226
+ - **Content-Type**: Not defined
227
+ - **Accept**: application/json
228
+
229
+
160
230
  ## get_all_accounts_health
161
231
 
162
232
  > <GetAllAccountsHealth200Response> get_all_accounts_health(opts)
@@ -0,0 +1,22 @@
1
+ # Zernio::GetAccountPosts200Response
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **status** | **String** | | [optional] |
8
+ | **posts** | [**Array&lt;GetAccountPosts200ResponsePostsInner&gt;**](GetAccountPosts200ResponsePostsInner.md) | | [optional] |
9
+ | **last_updated** | **Time** | | [optional] |
10
+
11
+ ## Example
12
+
13
+ ```ruby
14
+ require 'zernio-sdk'
15
+
16
+ instance = Zernio::GetAccountPosts200Response.new(
17
+ status: null,
18
+ posts: null,
19
+ last_updated: null
20
+ )
21
+ ```
22
+
@@ -0,0 +1,42 @@
1
+ # Zernio::GetAccountPosts200ResponsePostsInner
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **id** | **String** | The platform&#39;s own post id (the video ID on YouTube) | [optional] |
8
+ | **platform** | **String** | | [optional] |
9
+ | **message** | **String** | Caption or title, empty string when the post has no text | [optional] |
10
+ | **created_time** | **Time** | | [optional] |
11
+ | **permalink** | **String** | Public URL of the post on the platform | [optional] |
12
+ | **picture** | **String** | Thumbnail or media URL | [optional] |
13
+ | **media_type** | **String** | | [optional] |
14
+ | **comment_count** | **Integer** | | [optional] |
15
+ | **like_count** | **Integer** | | [optional] |
16
+ | **reaction_count** | **Integer** | Facebook and LinkedIn only | [optional] |
17
+ | **share_count** | **Integer** | | [optional] |
18
+ | **cid** | **String** | Bluesky content id, required to reply to the post | [optional] |
19
+ | **subreddit** | **String** | Reddit only | [optional] |
20
+
21
+ ## Example
22
+
23
+ ```ruby
24
+ require 'zernio-sdk'
25
+
26
+ instance = Zernio::GetAccountPosts200ResponsePostsInner.new(
27
+ id: null,
28
+ platform: null,
29
+ message: null,
30
+ created_time: null,
31
+ permalink: null,
32
+ picture: null,
33
+ media_type: null,
34
+ comment_count: null,
35
+ like_count: null,
36
+ reaction_count: null,
37
+ share_count: null,
38
+ cid: null,
39
+ subreddit: null
40
+ )
41
+ ```
42
+
data/docs/MessagesApi.md CHANGED
@@ -854,7 +854,7 @@ end
854
854
 
855
855
  Send message
856
856
 
857
- Send a message in a conversation. Supports text, attachments, quick replies, buttons, templates, and message tags. Attachment and interactive message support varies by platform. WhatsApp template messages: to send an approved template into this conversation (required when the 24-hour customer-service window is closed), use the `template` field with a single element carrying the template reference: `{ \"elements\": [{ \"name\": ..., \"language\": ..., \"components\": [...] }] }`. See the `template` field below for the exact shape. To send a template to a phone number you have no conversation with yet, use the create-conversation endpoint (POST /v1/inbox/conversations) instead. WhatsApp rich interactive messages (list, CTA URL, Flow, location request) are available via the `interactive` field. Tap events are delivered through the `message.received` webhook with WhatsApp-specific `metadata` fields (`interactiveType`, `interactiveId`, `flowResponseJson`, `flowResponseData`). **Idempotency:** send an `Idempotency-Key` header to make retries safe (e.g. after a client-side timeout where delivery is unknown): same key + same body replays the original response (with `Idempotent-Replayed: true`) instead of sending the message a second time; same key + different body returns 422; a key still in flight returns 409. Works for JSON and multipart (file upload) requests alike. Keys are retained for 24 hours. Only successful (2xx) responses are stored for replay: if the request throws or returns a non-2xx status, the key is released so the same key can be retried once the problem is fixed. The header therefore protects the \"request succeeded but the response was lost\" case. For an ambiguous failure (a 5xx or a network timeout), reconcile before retrying: a failure after the platform already accepted the message also releases the key, and a blind retry could send it twice. List the conversation's messages first, and treat an empty result as inconclusive rather than as proof nothing was sent, since a send that failed while being recorded leaves no trace on our side.
857
+ Send a message in a conversation. Supports text, attachments, quick replies, buttons, templates, and message tags. Attachment and interactive message support varies by platform. WhatsApp per-recipient rate limit: WhatsApp caps how many messages you may send to the same recipient in a short window and rejects the excess with error code `131056` (\"Too many messages sent to this recipient\"). Pace sends to a single recipient at roughly 10 per minute; bursts above that return a `400` with code `131056`. Sends to other recipients are unaffected, so parallelise across recipients rather than flooding one. WhatsApp template messages: to send an approved template into this conversation (required when the 24-hour customer-service window is closed), use the `template` field with a single element carrying the template reference: `{ \"elements\": [{ \"name\": ..., \"language\": ..., \"components\": [...] }] }`. See the `template` field below for the exact shape. To send a template to a phone number you have no conversation with yet, use the create-conversation endpoint (POST /v1/inbox/conversations) instead. WhatsApp rich interactive messages (list, CTA URL, Flow, location request) are available via the `interactive` field. Tap events are delivered through the `message.received` webhook with WhatsApp-specific `metadata` fields (`interactiveType`, `interactiveId`, `flowResponseJson`, `flowResponseData`). **Idempotency:** send an `Idempotency-Key` header to make retries safe (e.g. after a client-side timeout where delivery is unknown): same key + same body replays the original response (with `Idempotent-Replayed: true`) instead of sending the message a second time; same key + different body returns 422; a key still in flight returns 409. Works for JSON and multipart (file upload) requests alike. Keys are retained for 24 hours. Only successful (2xx) responses are stored for replay: if the request throws or returns a non-2xx status, the key is released so the same key can be retried once the problem is fixed. The header therefore protects the \"request succeeded but the response was lost\" case. For an ambiguous failure (a 5xx or a network timeout), reconcile before retrying: a failure after the platform already accepted the message also releases the key, and a blind retry could send it twice. List the conversation's messages first, and treat an empty result as inconclusive rather than as proof nothing was sent, since a send that failed while being recorded leaves no trace on our side.
858
858
 
859
859
  ### Examples
860
860
 
@@ -145,6 +145,69 @@ module Zernio
145
145
  return data, status_code, headers
146
146
  end
147
147
 
148
+ # List posts published on the platform
149
+ # Returns the 25 most recent posts that exist on the platform for a connected account, read live from the platform API. This covers everything on the account, including posts that were never created through Zernio. Use it to obtain the platform's own post id, which the analytics endpoints take as input. On YouTube the returned `id` is the video ID that `GET /v1/analytics/youtube/daily-views`, `/video-retention` and `/demographics` expect as `videoId`, so this endpoint is what backs a video picker in your own UI. Not every field applies to every platform: `reactionCount` is Facebook and LinkedIn, `shareCount` is platform dependent, `cid` is the Bluesky content id needed to reply, and `subreddit` is Reddit only. Absent fields are omitted from the response. The account's token is refreshed before the call when it has expired. When the refresh cannot recover it, the response is a 401 with code `TOKEN_EXPIRED` and the account has to be reconnected.
150
+ # @param account_id [String]
151
+ # @param [Hash] opts the optional parameters
152
+ # @return [GetAccountPosts200Response]
153
+ def get_account_posts(account_id, opts = {})
154
+ data, _status_code, _headers = get_account_posts_with_http_info(account_id, opts)
155
+ data
156
+ end
157
+
158
+ # List posts published on the platform
159
+ # Returns the 25 most recent posts that exist on the platform for a connected account, read live from the platform API. This covers everything on the account, including posts that were never created through Zernio. Use it to obtain the platform&#39;s own post id, which the analytics endpoints take as input. On YouTube the returned &#x60;id&#x60; is the video ID that &#x60;GET /v1/analytics/youtube/daily-views&#x60;, &#x60;/video-retention&#x60; and &#x60;/demographics&#x60; expect as &#x60;videoId&#x60;, so this endpoint is what backs a video picker in your own UI. Not every field applies to every platform: &#x60;reactionCount&#x60; is Facebook and LinkedIn, &#x60;shareCount&#x60; is platform dependent, &#x60;cid&#x60; is the Bluesky content id needed to reply, and &#x60;subreddit&#x60; is Reddit only. Absent fields are omitted from the response. The account&#39;s token is refreshed before the call when it has expired. When the refresh cannot recover it, the response is a 401 with code &#x60;TOKEN_EXPIRED&#x60; and the account has to be reconnected.
160
+ # @param account_id [String]
161
+ # @param [Hash] opts the optional parameters
162
+ # @return [Array<(GetAccountPosts200Response, Integer, Hash)>] GetAccountPosts200Response data, response status code and response headers
163
+ def get_account_posts_with_http_info(account_id, opts = {})
164
+ if @api_client.config.debugging
165
+ @api_client.config.logger.debug 'Calling API: AccountsApi.get_account_posts ...'
166
+ end
167
+ # verify the required parameter 'account_id' is set
168
+ if @api_client.config.client_side_validation && account_id.nil?
169
+ fail ArgumentError, "Missing the required parameter 'account_id' when calling AccountsApi.get_account_posts"
170
+ end
171
+ # resource path
172
+ local_var_path = '/v1/accounts/{accountId}/posts'.sub('{' + 'accountId' + '}', CGI.escape(account_id.to_s))
173
+
174
+ # query parameters
175
+ query_params = opts[:query_params] || {}
176
+
177
+ # header parameters
178
+ header_params = opts[:header_params] || {}
179
+ # HTTP header 'Accept' (if needed)
180
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
181
+
182
+ # form parameters
183
+ form_params = opts[:form_params] || {}
184
+
185
+ # http body (model)
186
+ post_body = opts[:debug_body]
187
+
188
+ # return_type
189
+ return_type = opts[:debug_return_type] || 'GetAccountPosts200Response'
190
+
191
+ # auth_names
192
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
193
+
194
+ new_options = opts.merge(
195
+ :operation => :"AccountsApi.get_account_posts",
196
+ :header_params => header_params,
197
+ :query_params => query_params,
198
+ :form_params => form_params,
199
+ :body => post_body,
200
+ :auth_names => auth_names,
201
+ :return_type => return_type
202
+ )
203
+
204
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
205
+ if @api_client.config.debugging
206
+ @api_client.config.logger.debug "API called: AccountsApi#get_account_posts\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
207
+ end
208
+ return data, status_code, headers
209
+ end
210
+
148
211
  # Check accounts health
149
212
  # Returns health status of all connected accounts including token validity, permissions, and issues needing attention.
150
213
  # @param [Hash] opts the optional parameters
@@ -932,7 +932,7 @@ module Zernio
932
932
  end
933
933
 
934
934
  # Send message
935
- # Send a message in a conversation. Supports text, attachments, quick replies, buttons, templates, and message tags. Attachment and interactive message support varies by platform. WhatsApp template messages: to send an approved template into this conversation (required when the 24-hour customer-service window is closed), use the `template` field with a single element carrying the template reference: `{ \"elements\": [{ \"name\": ..., \"language\": ..., \"components\": [...] }] }`. See the `template` field below for the exact shape. To send a template to a phone number you have no conversation with yet, use the create-conversation endpoint (POST /v1/inbox/conversations) instead. WhatsApp rich interactive messages (list, CTA URL, Flow, location request) are available via the `interactive` field. Tap events are delivered through the `message.received` webhook with WhatsApp-specific `metadata` fields (`interactiveType`, `interactiveId`, `flowResponseJson`, `flowResponseData`). **Idempotency:** send an `Idempotency-Key` header to make retries safe (e.g. after a client-side timeout where delivery is unknown): same key + same body replays the original response (with `Idempotent-Replayed: true`) instead of sending the message a second time; same key + different body returns 422; a key still in flight returns 409. Works for JSON and multipart (file upload) requests alike. Keys are retained for 24 hours. Only successful (2xx) responses are stored for replay: if the request throws or returns a non-2xx status, the key is released so the same key can be retried once the problem is fixed. The header therefore protects the \"request succeeded but the response was lost\" case. For an ambiguous failure (a 5xx or a network timeout), reconcile before retrying: a failure after the platform already accepted the message also releases the key, and a blind retry could send it twice. List the conversation's messages first, and treat an empty result as inconclusive rather than as proof nothing was sent, since a send that failed while being recorded leaves no trace on our side.
935
+ # Send a message in a conversation. Supports text, attachments, quick replies, buttons, templates, and message tags. Attachment and interactive message support varies by platform. WhatsApp per-recipient rate limit: WhatsApp caps how many messages you may send to the same recipient in a short window and rejects the excess with error code `131056` (\"Too many messages sent to this recipient\"). Pace sends to a single recipient at roughly 10 per minute; bursts above that return a `400` with code `131056`. Sends to other recipients are unaffected, so parallelise across recipients rather than flooding one. WhatsApp template messages: to send an approved template into this conversation (required when the 24-hour customer-service window is closed), use the `template` field with a single element carrying the template reference: `{ \"elements\": [{ \"name\": ..., \"language\": ..., \"components\": [...] }] }`. See the `template` field below for the exact shape. To send a template to a phone number you have no conversation with yet, use the create-conversation endpoint (POST /v1/inbox/conversations) instead. WhatsApp rich interactive messages (list, CTA URL, Flow, location request) are available via the `interactive` field. Tap events are delivered through the `message.received` webhook with WhatsApp-specific `metadata` fields (`interactiveType`, `interactiveId`, `flowResponseJson`, `flowResponseData`). **Idempotency:** send an `Idempotency-Key` header to make retries safe (e.g. after a client-side timeout where delivery is unknown): same key + same body replays the original response (with `Idempotent-Replayed: true`) instead of sending the message a second time; same key + different body returns 422; a key still in flight returns 409. Works for JSON and multipart (file upload) requests alike. Keys are retained for 24 hours. Only successful (2xx) responses are stored for replay: if the request throws or returns a non-2xx status, the key is released so the same key can be retried once the problem is fixed. The header therefore protects the \"request succeeded but the response was lost\" case. For an ambiguous failure (a 5xx or a network timeout), reconcile before retrying: a failure after the platform already accepted the message also releases the key, and a blind retry could send it twice. List the conversation's messages first, and treat an empty result as inconclusive rather than as proof nothing was sent, since a send that failed while being recorded leaves no trace on our side.
936
936
  # @param conversation_id [String] Opaque conversation identifier, accepted verbatim from the list endpoint or from the conversationId on inbox webhooks. Format not to be assumed.
937
937
  # @param send_inbox_message_request [SendInboxMessageRequest]
938
938
  # @param [Hash] opts the optional parameters
@@ -944,7 +944,7 @@ module Zernio
944
944
  end
945
945
 
946
946
  # Send message
947
- # Send a message in a conversation. Supports text, attachments, quick replies, buttons, templates, and message tags. Attachment and interactive message support varies by platform. WhatsApp template messages: to send an approved template into this conversation (required when the 24-hour customer-service window is closed), use the &#x60;template&#x60; field with a single element carrying the template reference: &#x60;{ \&quot;elements\&quot;: [{ \&quot;name\&quot;: ..., \&quot;language\&quot;: ..., \&quot;components\&quot;: [...] }] }&#x60;. See the &#x60;template&#x60; field below for the exact shape. To send a template to a phone number you have no conversation with yet, use the create-conversation endpoint (POST /v1/inbox/conversations) instead. WhatsApp rich interactive messages (list, CTA URL, Flow, location request) are available via the &#x60;interactive&#x60; field. Tap events are delivered through the &#x60;message.received&#x60; webhook with WhatsApp-specific &#x60;metadata&#x60; fields (&#x60;interactiveType&#x60;, &#x60;interactiveId&#x60;, &#x60;flowResponseJson&#x60;, &#x60;flowResponseData&#x60;). **Idempotency:** send an &#x60;Idempotency-Key&#x60; header to make retries safe (e.g. after a client-side timeout where delivery is unknown): same key + same body replays the original response (with &#x60;Idempotent-Replayed: true&#x60;) instead of sending the message a second time; same key + different body returns 422; a key still in flight returns 409. Works for JSON and multipart (file upload) requests alike. Keys are retained for 24 hours. Only successful (2xx) responses are stored for replay: if the request throws or returns a non-2xx status, the key is released so the same key can be retried once the problem is fixed. The header therefore protects the \&quot;request succeeded but the response was lost\&quot; case. For an ambiguous failure (a 5xx or a network timeout), reconcile before retrying: a failure after the platform already accepted the message also releases the key, and a blind retry could send it twice. List the conversation&#39;s messages first, and treat an empty result as inconclusive rather than as proof nothing was sent, since a send that failed while being recorded leaves no trace on our side.
947
+ # Send a message in a conversation. Supports text, attachments, quick replies, buttons, templates, and message tags. Attachment and interactive message support varies by platform. WhatsApp per-recipient rate limit: WhatsApp caps how many messages you may send to the same recipient in a short window and rejects the excess with error code &#x60;131056&#x60; (\&quot;Too many messages sent to this recipient\&quot;). Pace sends to a single recipient at roughly 10 per minute; bursts above that return a &#x60;400&#x60; with code &#x60;131056&#x60;. Sends to other recipients are unaffected, so parallelise across recipients rather than flooding one. WhatsApp template messages: to send an approved template into this conversation (required when the 24-hour customer-service window is closed), use the &#x60;template&#x60; field with a single element carrying the template reference: &#x60;{ \&quot;elements\&quot;: [{ \&quot;name\&quot;: ..., \&quot;language\&quot;: ..., \&quot;components\&quot;: [...] }] }&#x60;. See the &#x60;template&#x60; field below for the exact shape. To send a template to a phone number you have no conversation with yet, use the create-conversation endpoint (POST /v1/inbox/conversations) instead. WhatsApp rich interactive messages (list, CTA URL, Flow, location request) are available via the &#x60;interactive&#x60; field. Tap events are delivered through the &#x60;message.received&#x60; webhook with WhatsApp-specific &#x60;metadata&#x60; fields (&#x60;interactiveType&#x60;, &#x60;interactiveId&#x60;, &#x60;flowResponseJson&#x60;, &#x60;flowResponseData&#x60;). **Idempotency:** send an &#x60;Idempotency-Key&#x60; header to make retries safe (e.g. after a client-side timeout where delivery is unknown): same key + same body replays the original response (with &#x60;Idempotent-Replayed: true&#x60;) instead of sending the message a second time; same key + different body returns 422; a key still in flight returns 409. Works for JSON and multipart (file upload) requests alike. Keys are retained for 24 hours. Only successful (2xx) responses are stored for replay: if the request throws or returns a non-2xx status, the key is released so the same key can be retried once the problem is fixed. The header therefore protects the \&quot;request succeeded but the response was lost\&quot; case. For an ambiguous failure (a 5xx or a network timeout), reconcile before retrying: a failure after the platform already accepted the message also releases the key, and a blind retry could send it twice. List the conversation&#39;s messages first, and treat an empty result as inconclusive rather than as proof nothing was sent, since a send that failed while being recorded leaves no trace on our side.
948
948
  # @param conversation_id [String] Opaque conversation identifier, accepted verbatim from the list endpoint or from the conversationId on inbox webhooks. Format not to be assumed.
949
949
  # @param send_inbox_message_request [SendInboxMessageRequest]
950
950
  # @param [Hash] opts the optional parameters
@@ -0,0 +1,201 @@
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 'date'
14
+ require 'time'
15
+
16
+ module Zernio
17
+ class GetAccountPosts200Response < ApiModelBase
18
+ attr_accessor :status
19
+
20
+ attr_accessor :posts
21
+
22
+ attr_accessor :last_updated
23
+
24
+ class EnumAttributeValidator
25
+ attr_reader :datatype
26
+ attr_reader :allowable_values
27
+
28
+ def initialize(datatype, allowable_values)
29
+ @allowable_values = allowable_values.map do |value|
30
+ case datatype.to_s
31
+ when /Integer/i
32
+ value.to_i
33
+ when /Float/i
34
+ value.to_f
35
+ else
36
+ value
37
+ end
38
+ end
39
+ end
40
+
41
+ def valid?(value)
42
+ !value || allowable_values.include?(value)
43
+ end
44
+ end
45
+
46
+ # Attribute mapping from ruby-style variable name to JSON key.
47
+ def self.attribute_map
48
+ {
49
+ :'status' => :'status',
50
+ :'posts' => :'posts',
51
+ :'last_updated' => :'lastUpdated'
52
+ }
53
+ end
54
+
55
+ # Returns attribute mapping this model knows about
56
+ def self.acceptable_attribute_map
57
+ attribute_map
58
+ end
59
+
60
+ # Returns all the JSON keys this model knows about
61
+ def self.acceptable_attributes
62
+ acceptable_attribute_map.values
63
+ end
64
+
65
+ # Attribute type mapping.
66
+ def self.openapi_types
67
+ {
68
+ :'status' => :'String',
69
+ :'posts' => :'Array<GetAccountPosts200ResponsePostsInner>',
70
+ :'last_updated' => :'Time'
71
+ }
72
+ end
73
+
74
+ # List of attributes with nullable: true
75
+ def self.openapi_nullable
76
+ Set.new([
77
+ ])
78
+ end
79
+
80
+ # Initializes the object
81
+ # @param [Hash] attributes Model attributes in the form of hash
82
+ def initialize(attributes = {})
83
+ if (!attributes.is_a?(Hash))
84
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::GetAccountPosts200Response` initialize method"
85
+ end
86
+
87
+ # check to see if the attribute exists and convert string to symbol for hash key
88
+ acceptable_attribute_map = self.class.acceptable_attribute_map
89
+ attributes = attributes.each_with_object({}) { |(k, v), h|
90
+ if (!acceptable_attribute_map.key?(k.to_sym))
91
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::GetAccountPosts200Response`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
92
+ end
93
+ h[k.to_sym] = v
94
+ }
95
+
96
+ if attributes.key?(:'status')
97
+ self.status = attributes[:'status']
98
+ end
99
+
100
+ if attributes.key?(:'posts')
101
+ if (value = attributes[:'posts']).is_a?(Array)
102
+ self.posts = value
103
+ end
104
+ end
105
+
106
+ if attributes.key?(:'last_updated')
107
+ self.last_updated = attributes[:'last_updated']
108
+ end
109
+ end
110
+
111
+ # Show invalid properties with the reasons. Usually used together with valid?
112
+ # @return Array for valid properties with the reasons
113
+ def list_invalid_properties
114
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
115
+ invalid_properties = Array.new
116
+ invalid_properties
117
+ end
118
+
119
+ # Check to see if the all the properties in the model are valid
120
+ # @return true if the model is valid
121
+ def valid?
122
+ warn '[DEPRECATED] the `valid?` method is obsolete'
123
+ status_validator = EnumAttributeValidator.new('String', ["success"])
124
+ return false unless status_validator.valid?(@status)
125
+ true
126
+ end
127
+
128
+ # Custom attribute writer method checking allowed values (enum).
129
+ # @param [Object] status Object to be assigned
130
+ def status=(status)
131
+ validator = EnumAttributeValidator.new('String', ["success"])
132
+ unless validator.valid?(status)
133
+ fail ArgumentError, "invalid value for \"status\", must be one of #{validator.allowable_values}."
134
+ end
135
+ @status = status
136
+ end
137
+
138
+ # Checks equality by comparing each attribute.
139
+ # @param [Object] Object to be compared
140
+ def ==(o)
141
+ return true if self.equal?(o)
142
+ self.class == o.class &&
143
+ status == o.status &&
144
+ posts == o.posts &&
145
+ last_updated == o.last_updated
146
+ end
147
+
148
+ # @see the `==` method
149
+ # @param [Object] Object to be compared
150
+ def eql?(o)
151
+ self == o
152
+ end
153
+
154
+ # Calculates hash code according to all attributes.
155
+ # @return [Integer] Hash code
156
+ def hash
157
+ [status, posts, last_updated].hash
158
+ end
159
+
160
+ # Builds the object from hash
161
+ # @param [Hash] attributes Model attributes in the form of hash
162
+ # @return [Object] Returns the model itself
163
+ def self.build_from_hash(attributes)
164
+ return nil unless attributes.is_a?(Hash)
165
+ attributes = attributes.transform_keys(&:to_sym)
166
+ transformed_hash = {}
167
+ openapi_types.each_pair do |key, type|
168
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
169
+ transformed_hash["#{key}"] = nil
170
+ elsif type =~ /\AArray<(.*)>/i
171
+ # check to ensure the input is an array given that the attribute
172
+ # is documented as an array but the input is not
173
+ if attributes[attribute_map[key]].is_a?(Array)
174
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
175
+ end
176
+ elsif !attributes[attribute_map[key]].nil?
177
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
178
+ end
179
+ end
180
+ new(transformed_hash)
181
+ end
182
+
183
+ # Returns the object in the form of hash
184
+ # @return [Hash] Returns the object in the form of hash
185
+ def to_hash
186
+ hash = {}
187
+ self.class.attribute_map.each_pair do |attr, param|
188
+ value = self.send(attr)
189
+ if value.nil?
190
+ is_nullable = self.class.openapi_nullable.include?(attr)
191
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
192
+ end
193
+
194
+ hash[param] = _to_hash(value)
195
+ end
196
+ hash
197
+ end
198
+
199
+ end
200
+
201
+ end
@@ -0,0 +1,262 @@
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 'date'
14
+ require 'time'
15
+
16
+ module Zernio
17
+ class GetAccountPosts200ResponsePostsInner < ApiModelBase
18
+ # The platform's own post id (the video ID on YouTube)
19
+ attr_accessor :id
20
+
21
+ attr_accessor :platform
22
+
23
+ # Caption or title, empty string when the post has no text
24
+ attr_accessor :message
25
+
26
+ attr_accessor :created_time
27
+
28
+ # Public URL of the post on the platform
29
+ attr_accessor :permalink
30
+
31
+ # Thumbnail or media URL
32
+ attr_accessor :picture
33
+
34
+ attr_accessor :media_type
35
+
36
+ attr_accessor :comment_count
37
+
38
+ attr_accessor :like_count
39
+
40
+ # Facebook and LinkedIn only
41
+ attr_accessor :reaction_count
42
+
43
+ attr_accessor :share_count
44
+
45
+ # Bluesky content id, required to reply to the post
46
+ attr_accessor :cid
47
+
48
+ # Reddit only
49
+ attr_accessor :subreddit
50
+
51
+ # Attribute mapping from ruby-style variable name to JSON key.
52
+ def self.attribute_map
53
+ {
54
+ :'id' => :'id',
55
+ :'platform' => :'platform',
56
+ :'message' => :'message',
57
+ :'created_time' => :'createdTime',
58
+ :'permalink' => :'permalink',
59
+ :'picture' => :'picture',
60
+ :'media_type' => :'mediaType',
61
+ :'comment_count' => :'commentCount',
62
+ :'like_count' => :'likeCount',
63
+ :'reaction_count' => :'reactionCount',
64
+ :'share_count' => :'shareCount',
65
+ :'cid' => :'cid',
66
+ :'subreddit' => :'subreddit'
67
+ }
68
+ end
69
+
70
+ # Returns attribute mapping this model knows about
71
+ def self.acceptable_attribute_map
72
+ attribute_map
73
+ end
74
+
75
+ # Returns all the JSON keys this model knows about
76
+ def self.acceptable_attributes
77
+ acceptable_attribute_map.values
78
+ end
79
+
80
+ # Attribute type mapping.
81
+ def self.openapi_types
82
+ {
83
+ :'id' => :'String',
84
+ :'platform' => :'String',
85
+ :'message' => :'String',
86
+ :'created_time' => :'Time',
87
+ :'permalink' => :'String',
88
+ :'picture' => :'String',
89
+ :'media_type' => :'String',
90
+ :'comment_count' => :'Integer',
91
+ :'like_count' => :'Integer',
92
+ :'reaction_count' => :'Integer',
93
+ :'share_count' => :'Integer',
94
+ :'cid' => :'String',
95
+ :'subreddit' => :'String'
96
+ }
97
+ end
98
+
99
+ # List of attributes with nullable: true
100
+ def self.openapi_nullable
101
+ Set.new([
102
+ ])
103
+ end
104
+
105
+ # Initializes the object
106
+ # @param [Hash] attributes Model attributes in the form of hash
107
+ def initialize(attributes = {})
108
+ if (!attributes.is_a?(Hash))
109
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::GetAccountPosts200ResponsePostsInner` initialize method"
110
+ end
111
+
112
+ # check to see if the attribute exists and convert string to symbol for hash key
113
+ acceptable_attribute_map = self.class.acceptable_attribute_map
114
+ attributes = attributes.each_with_object({}) { |(k, v), h|
115
+ if (!acceptable_attribute_map.key?(k.to_sym))
116
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::GetAccountPosts200ResponsePostsInner`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
117
+ end
118
+ h[k.to_sym] = v
119
+ }
120
+
121
+ if attributes.key?(:'id')
122
+ self.id = attributes[:'id']
123
+ end
124
+
125
+ if attributes.key?(:'platform')
126
+ self.platform = attributes[:'platform']
127
+ end
128
+
129
+ if attributes.key?(:'message')
130
+ self.message = attributes[:'message']
131
+ end
132
+
133
+ if attributes.key?(:'created_time')
134
+ self.created_time = attributes[:'created_time']
135
+ end
136
+
137
+ if attributes.key?(:'permalink')
138
+ self.permalink = attributes[:'permalink']
139
+ end
140
+
141
+ if attributes.key?(:'picture')
142
+ self.picture = attributes[:'picture']
143
+ end
144
+
145
+ if attributes.key?(:'media_type')
146
+ self.media_type = attributes[:'media_type']
147
+ end
148
+
149
+ if attributes.key?(:'comment_count')
150
+ self.comment_count = attributes[:'comment_count']
151
+ end
152
+
153
+ if attributes.key?(:'like_count')
154
+ self.like_count = attributes[:'like_count']
155
+ end
156
+
157
+ if attributes.key?(:'reaction_count')
158
+ self.reaction_count = attributes[:'reaction_count']
159
+ end
160
+
161
+ if attributes.key?(:'share_count')
162
+ self.share_count = attributes[:'share_count']
163
+ end
164
+
165
+ if attributes.key?(:'cid')
166
+ self.cid = attributes[:'cid']
167
+ end
168
+
169
+ if attributes.key?(:'subreddit')
170
+ self.subreddit = attributes[:'subreddit']
171
+ end
172
+ end
173
+
174
+ # Show invalid properties with the reasons. Usually used together with valid?
175
+ # @return Array for valid properties with the reasons
176
+ def list_invalid_properties
177
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
178
+ invalid_properties = Array.new
179
+ invalid_properties
180
+ end
181
+
182
+ # Check to see if the all the properties in the model are valid
183
+ # @return true if the model is valid
184
+ def valid?
185
+ warn '[DEPRECATED] the `valid?` method is obsolete'
186
+ true
187
+ end
188
+
189
+ # Checks equality by comparing each attribute.
190
+ # @param [Object] Object to be compared
191
+ def ==(o)
192
+ return true if self.equal?(o)
193
+ self.class == o.class &&
194
+ id == o.id &&
195
+ platform == o.platform &&
196
+ message == o.message &&
197
+ created_time == o.created_time &&
198
+ permalink == o.permalink &&
199
+ picture == o.picture &&
200
+ media_type == o.media_type &&
201
+ comment_count == o.comment_count &&
202
+ like_count == o.like_count &&
203
+ reaction_count == o.reaction_count &&
204
+ share_count == o.share_count &&
205
+ cid == o.cid &&
206
+ subreddit == o.subreddit
207
+ end
208
+
209
+ # @see the `==` method
210
+ # @param [Object] Object to be compared
211
+ def eql?(o)
212
+ self == o
213
+ end
214
+
215
+ # Calculates hash code according to all attributes.
216
+ # @return [Integer] Hash code
217
+ def hash
218
+ [id, platform, message, created_time, permalink, picture, media_type, comment_count, like_count, reaction_count, share_count, cid, subreddit].hash
219
+ end
220
+
221
+ # Builds the object from hash
222
+ # @param [Hash] attributes Model attributes in the form of hash
223
+ # @return [Object] Returns the model itself
224
+ def self.build_from_hash(attributes)
225
+ return nil unless attributes.is_a?(Hash)
226
+ attributes = attributes.transform_keys(&:to_sym)
227
+ transformed_hash = {}
228
+ openapi_types.each_pair do |key, type|
229
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
230
+ transformed_hash["#{key}"] = nil
231
+ elsif type =~ /\AArray<(.*)>/i
232
+ # check to ensure the input is an array given that the attribute
233
+ # is documented as an array but the input is not
234
+ if attributes[attribute_map[key]].is_a?(Array)
235
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
236
+ end
237
+ elsif !attributes[attribute_map[key]].nil?
238
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
239
+ end
240
+ end
241
+ new(transformed_hash)
242
+ end
243
+
244
+ # Returns the object in the form of hash
245
+ # @return [Hash] Returns the object in the form of hash
246
+ def to_hash
247
+ hash = {}
248
+ self.class.attribute_map.each_pair do |attr, param|
249
+ value = self.send(attr)
250
+ if value.nil?
251
+ is_nullable = self.class.openapi_nullable.include?(attr)
252
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
253
+ end
254
+
255
+ hash[param] = _to_hash(value)
256
+ end
257
+ hash
258
+ end
259
+
260
+ end
261
+
262
+ end
@@ -11,5 +11,5 @@ Generator version: 7.19.0
11
11
  =end
12
12
 
13
13
  module Zernio
14
- VERSION = '0.0.786'
14
+ VERSION = '0.0.787'
15
15
  end
data/lib/zernio-sdk.rb CHANGED
@@ -496,6 +496,8 @@ require 'zernio-sdk/models/get_account_health200_response_permissions_posting_in
496
496
  require 'zernio-sdk/models/get_account_health200_response_platform_connection'
497
497
  require 'zernio-sdk/models/get_account_health200_response_platform_connection_meta_error'
498
498
  require 'zernio-sdk/models/get_account_health200_response_token_status'
499
+ require 'zernio-sdk/models/get_account_posts200_response'
500
+ require 'zernio-sdk/models/get_account_posts200_response_posts_inner'
499
501
  require 'zernio-sdk/models/get_ad200_response'
500
502
  require 'zernio-sdk/models/get_ad_account_finance200_response'
501
503
  require 'zernio-sdk/models/get_ad_account_finance200_response_funding_source'
data/openapi.yaml CHANGED
@@ -16651,6 +16651,80 @@ paths:
16651
16651
  '400': { $ref: '#/components/responses/BadRequest' }
16652
16652
  '401': { $ref: '#/components/responses/Unauthorized' }
16653
16653
  '404': { $ref: '#/components/responses/NotFound' }
16654
+ /v1/accounts/{accountId}/posts:
16655
+ get:
16656
+ x-resource-group: "accounts"
16657
+ operationId: getAccountPosts
16658
+ tags: [Accounts]
16659
+ x-platforms: ["facebook", "instagram", "twitter", "bluesky", "threads", "youtube", "linkedin", "reddit", "tiktok", "pinterest"]
16660
+ summary: List posts published on the platform
16661
+ description: |
16662
+ Returns the 25 most recent posts that exist on the platform for a connected account, read
16663
+ live from the platform API. This covers everything on the account, including posts that
16664
+ were never created through Zernio.
16665
+
16666
+ Use it to obtain the platform's own post id, which the analytics endpoints take as input.
16667
+ On YouTube the returned `id` is the video ID that `GET /v1/analytics/youtube/daily-views`,
16668
+ `/video-retention` and `/demographics` expect as `videoId`, so this endpoint is what backs
16669
+ a video picker in your own UI.
16670
+
16671
+ Not every field applies to every platform: `reactionCount` is Facebook and LinkedIn,
16672
+ `shareCount` is platform dependent, `cid` is the Bluesky content id needed to reply, and
16673
+ `subreddit` is Reddit only. Absent fields are omitted from the response.
16674
+
16675
+ The account's token is refreshed before the call when it has expired. When the refresh
16676
+ cannot recover it, the response is a 401 with code `TOKEN_EXPIRED` and the account has to
16677
+ be reconnected.
16678
+ parameters:
16679
+ - name: accountId
16680
+ in: path
16681
+ required: true
16682
+ schema: { type: string }
16683
+ responses:
16684
+ '200':
16685
+ description: Posts list
16686
+ content:
16687
+ application/json:
16688
+ schema:
16689
+ type: object
16690
+ properties:
16691
+ status: { type: string, enum: [success] }
16692
+ posts:
16693
+ type: array
16694
+ items:
16695
+ type: object
16696
+ properties:
16697
+ id: { type: string, description: "The platform's own post id (the video ID on YouTube)" }
16698
+ platform: { type: string }
16699
+ message: { type: string, description: 'Caption or title, empty string when the post has no text' }
16700
+ createdTime: { type: string, format: date-time }
16701
+ permalink: { type: string, description: 'Public URL of the post on the platform' }
16702
+ picture: { type: string, description: 'Thumbnail or media URL' }
16703
+ mediaType: { type: string }
16704
+ commentCount: { type: integer }
16705
+ likeCount: { type: integer }
16706
+ reactionCount: { type: integer, description: 'Facebook and LinkedIn only' }
16707
+ shareCount: { type: integer }
16708
+ cid: { type: string, description: 'Bluesky content id, required to reply to the post' }
16709
+ subreddit: { type: string, description: 'Reddit only' }
16710
+ lastUpdated: { type: string, format: date-time }
16711
+ example:
16712
+ status: "success"
16713
+ posts:
16714
+ - id: "dQw4w9WgXcQ"
16715
+ platform: "youtube"
16716
+ message: "How to schedule a post\n\nA short walkthrough."
16717
+ createdTime: "2026-08-21T09:14:03.000Z"
16718
+ permalink: "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
16719
+ picture: "https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg"
16720
+ mediaType: "video"
16721
+ commentCount: 12
16722
+ likeCount: 340
16723
+ lastUpdated: "2026-08-28T11:02:44.512Z"
16724
+ '400':
16725
+ description: 'Invalid accountId, platform does not support posts listing, or the account has no access token'
16726
+ '401': { $ref: '#/components/responses/Unauthorized' }
16727
+ '404': { $ref: '#/components/responses/NotFound' }
16654
16728
  /v1/accounts/{accountId}/follow-status/{userId}:
16655
16729
  get:
16656
16730
  operationId: getInstagramFollowStatus
@@ -26629,6 +26703,13 @@ paths:
26629
26703
  buttons, templates, and message tags. Attachment and interactive message
26630
26704
  support varies by platform.
26631
26705
 
26706
+ WhatsApp per-recipient rate limit: WhatsApp caps how many messages you may
26707
+ send to the same recipient in a short window and rejects the excess with
26708
+ error code `131056` ("Too many messages sent to this recipient"). Pace
26709
+ sends to a single recipient at roughly 10 per minute; bursts above that
26710
+ return a `400` with code `131056`. Sends to other recipients are
26711
+ unaffected, so parallelise across recipients rather than flooding one.
26712
+
26632
26713
  WhatsApp template messages: to send an approved template into this
26633
26714
  conversation (required when the 24-hour customer-service window is
26634
26715
  closed), use the `template` field with a single element carrying the
@@ -56,6 +56,18 @@ describe 'AccountsApi' do
56
56
  end
57
57
  end
58
58
 
59
+ # unit tests for get_account_posts
60
+ # List posts published on the platform
61
+ # Returns the 25 most recent posts that exist on the platform for a connected account, read live from the platform API. This covers everything on the account, including posts that were never created through Zernio. Use it to obtain the platform&#39;s own post id, which the analytics endpoints take as input. On YouTube the returned &#x60;id&#x60; is the video ID that &#x60;GET /v1/analytics/youtube/daily-views&#x60;, &#x60;/video-retention&#x60; and &#x60;/demographics&#x60; expect as &#x60;videoId&#x60;, so this endpoint is what backs a video picker in your own UI. Not every field applies to every platform: &#x60;reactionCount&#x60; is Facebook and LinkedIn, &#x60;shareCount&#x60; is platform dependent, &#x60;cid&#x60; is the Bluesky content id needed to reply, and &#x60;subreddit&#x60; is Reddit only. Absent fields are omitted from the response. The account&#39;s token is refreshed before the call when it has expired. When the refresh cannot recover it, the response is a 401 with code &#x60;TOKEN_EXPIRED&#x60; and the account has to be reconnected.
62
+ # @param account_id
63
+ # @param [Hash] opts the optional parameters
64
+ # @return [GetAccountPosts200Response]
65
+ describe 'get_account_posts test' do
66
+ it 'should work' do
67
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
68
+ end
69
+ end
70
+
59
71
  # unit tests for get_all_accounts_health
60
72
  # Check accounts health
61
73
  # Returns health status of all connected accounts including token validity, permissions, and issues needing attention.
@@ -196,7 +196,7 @@ describe 'MessagesApi' do
196
196
 
197
197
  # unit tests for send_inbox_message
198
198
  # Send message
199
- # Send a message in a conversation. Supports text, attachments, quick replies, buttons, templates, and message tags. Attachment and interactive message support varies by platform. WhatsApp template messages: to send an approved template into this conversation (required when the 24-hour customer-service window is closed), use the &#x60;template&#x60; field with a single element carrying the template reference: &#x60;{ \&quot;elements\&quot;: [{ \&quot;name\&quot;: ..., \&quot;language\&quot;: ..., \&quot;components\&quot;: [...] }] }&#x60;. See the &#x60;template&#x60; field below for the exact shape. To send a template to a phone number you have no conversation with yet, use the create-conversation endpoint (POST /v1/inbox/conversations) instead. WhatsApp rich interactive messages (list, CTA URL, Flow, location request) are available via the &#x60;interactive&#x60; field. Tap events are delivered through the &#x60;message.received&#x60; webhook with WhatsApp-specific &#x60;metadata&#x60; fields (&#x60;interactiveType&#x60;, &#x60;interactiveId&#x60;, &#x60;flowResponseJson&#x60;, &#x60;flowResponseData&#x60;). **Idempotency:** send an &#x60;Idempotency-Key&#x60; header to make retries safe (e.g. after a client-side timeout where delivery is unknown): same key + same body replays the original response (with &#x60;Idempotent-Replayed: true&#x60;) instead of sending the message a second time; same key + different body returns 422; a key still in flight returns 409. Works for JSON and multipart (file upload) requests alike. Keys are retained for 24 hours. Only successful (2xx) responses are stored for replay: if the request throws or returns a non-2xx status, the key is released so the same key can be retried once the problem is fixed. The header therefore protects the \&quot;request succeeded but the response was lost\&quot; case. For an ambiguous failure (a 5xx or a network timeout), reconcile before retrying: a failure after the platform already accepted the message also releases the key, and a blind retry could send it twice. List the conversation&#39;s messages first, and treat an empty result as inconclusive rather than as proof nothing was sent, since a send that failed while being recorded leaves no trace on our side.
199
+ # Send a message in a conversation. Supports text, attachments, quick replies, buttons, templates, and message tags. Attachment and interactive message support varies by platform. WhatsApp per-recipient rate limit: WhatsApp caps how many messages you may send to the same recipient in a short window and rejects the excess with error code &#x60;131056&#x60; (\&quot;Too many messages sent to this recipient\&quot;). Pace sends to a single recipient at roughly 10 per minute; bursts above that return a &#x60;400&#x60; with code &#x60;131056&#x60;. Sends to other recipients are unaffected, so parallelise across recipients rather than flooding one. WhatsApp template messages: to send an approved template into this conversation (required when the 24-hour customer-service window is closed), use the &#x60;template&#x60; field with a single element carrying the template reference: &#x60;{ \&quot;elements\&quot;: [{ \&quot;name\&quot;: ..., \&quot;language\&quot;: ..., \&quot;components\&quot;: [...] }] }&#x60;. See the &#x60;template&#x60; field below for the exact shape. To send a template to a phone number you have no conversation with yet, use the create-conversation endpoint (POST /v1/inbox/conversations) instead. WhatsApp rich interactive messages (list, CTA URL, Flow, location request) are available via the &#x60;interactive&#x60; field. Tap events are delivered through the &#x60;message.received&#x60; webhook with WhatsApp-specific &#x60;metadata&#x60; fields (&#x60;interactiveType&#x60;, &#x60;interactiveId&#x60;, &#x60;flowResponseJson&#x60;, &#x60;flowResponseData&#x60;). **Idempotency:** send an &#x60;Idempotency-Key&#x60; header to make retries safe (e.g. after a client-side timeout where delivery is unknown): same key + same body replays the original response (with &#x60;Idempotent-Replayed: true&#x60;) instead of sending the message a second time; same key + different body returns 422; a key still in flight returns 409. Works for JSON and multipart (file upload) requests alike. Keys are retained for 24 hours. Only successful (2xx) responses are stored for replay: if the request throws or returns a non-2xx status, the key is released so the same key can be retried once the problem is fixed. The header therefore protects the \&quot;request succeeded but the response was lost\&quot; case. For an ambiguous failure (a 5xx or a network timeout), reconcile before retrying: a failure after the platform already accepted the message also releases the key, and a blind retry could send it twice. List the conversation&#39;s messages first, and treat an empty result as inconclusive rather than as proof nothing was sent, since a send that failed while being recorded leaves no trace on our side.
200
200
  # @param conversation_id Opaque conversation identifier, accepted verbatim from the list endpoint or from the conversationId on inbox webhooks. Format not to be assumed.
201
201
  # @param send_inbox_message_request
202
202
  # @param [Hash] opts the optional parameters
@@ -0,0 +1,108 @@
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::GetAccountPosts200ResponsePostsInner
18
+ # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
+ # Please update as you see appropriate
20
+ describe Zernio::GetAccountPosts200ResponsePostsInner do
21
+ #let(:instance) { Zernio::GetAccountPosts200ResponsePostsInner.new }
22
+
23
+ describe 'test an instance of GetAccountPosts200ResponsePostsInner' do
24
+ it 'should create an instance of GetAccountPosts200ResponsePostsInner' do
25
+ # uncomment below to test the instance creation
26
+ #expect(instance).to be_instance_of(Zernio::GetAccountPosts200ResponsePostsInner)
27
+ end
28
+ end
29
+
30
+ describe 'test attribute "id"' 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 "platform"' 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 "message"' 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 "created_time"' 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 "permalink"' 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 "picture"' 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 "media_type"' 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 "comment_count"' 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 "like_count"' 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 "reaction_count"' 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 "share_count"' 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 "cid"' 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 "subreddit"' 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
+ end
@@ -0,0 +1,52 @@
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::GetAccountPosts200Response
18
+ # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
+ # Please update as you see appropriate
20
+ describe Zernio::GetAccountPosts200Response do
21
+ #let(:instance) { Zernio::GetAccountPosts200Response.new }
22
+
23
+ describe 'test an instance of GetAccountPosts200Response' do
24
+ it 'should create an instance of GetAccountPosts200Response' do
25
+ # uncomment below to test the instance creation
26
+ #expect(instance).to be_instance_of(Zernio::GetAccountPosts200Response)
27
+ end
28
+ end
29
+
30
+ describe 'test attribute "status"' do
31
+ it 'should work' do
32
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
33
+ # validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["success"])
34
+ # validator.allowable_values.each do |value|
35
+ # expect { instance.status = value }.not_to raise_error
36
+ # end
37
+ end
38
+ end
39
+
40
+ describe 'test attribute "posts"' do
41
+ it 'should work' do
42
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
43
+ end
44
+ end
45
+
46
+ describe 'test attribute "last_updated"' do
47
+ it 'should work' do
48
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
49
+ end
50
+ end
51
+
52
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zernio-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.786
4
+ version: 0.0.787
5
5
  platform: ruby
6
6
  authors:
7
7
  - OpenAPI-Generator
@@ -576,6 +576,8 @@ files:
576
576
  - docs/GetAccountHealth200ResponsePlatformConnection.md
577
577
  - docs/GetAccountHealth200ResponsePlatformConnectionMetaError.md
578
578
  - docs/GetAccountHealth200ResponseTokenStatus.md
579
+ - docs/GetAccountPosts200Response.md
580
+ - docs/GetAccountPosts200ResponsePostsInner.md
579
581
  - docs/GetAd200Response.md
580
582
  - docs/GetAdAccountFinance200Response.md
581
583
  - docs/GetAdAccountFinance200ResponseFundingSource.md
@@ -2430,6 +2432,8 @@ files:
2430
2432
  - lib/zernio-sdk/models/get_account_health200_response_platform_connection.rb
2431
2433
  - lib/zernio-sdk/models/get_account_health200_response_platform_connection_meta_error.rb
2432
2434
  - lib/zernio-sdk/models/get_account_health200_response_token_status.rb
2435
+ - lib/zernio-sdk/models/get_account_posts200_response.rb
2436
+ - lib/zernio-sdk/models/get_account_posts200_response_posts_inner.rb
2433
2437
  - lib/zernio-sdk/models/get_ad200_response.rb
2434
2438
  - lib/zernio-sdk/models/get_ad_account_finance200_response.rb
2435
2439
  - lib/zernio-sdk/models/get_ad_account_finance200_response_funding_source.rb
@@ -4243,6 +4247,8 @@ files:
4243
4247
  - spec/models/get_account_health200_response_platform_connection_spec.rb
4244
4248
  - spec/models/get_account_health200_response_spec.rb
4245
4249
  - spec/models/get_account_health200_response_token_status_spec.rb
4250
+ - spec/models/get_account_posts200_response_posts_inner_spec.rb
4251
+ - spec/models/get_account_posts200_response_spec.rb
4246
4252
  - spec/models/get_ad200_response_spec.rb
4247
4253
  - spec/models/get_ad_account_finance200_response_funding_source_spec.rb
4248
4254
  - spec/models/get_ad_account_finance200_response_spec.rb
@@ -6476,6 +6482,7 @@ test_files:
6476
6482
  - spec/models/discord_platform_data_poll_answers_inner_spec.rb
6477
6483
  - spec/models/webhook_payload_message_deleted_spec.rb
6478
6484
  - spec/models/submit_whats_app_number_kyc_request_spec.rb
6485
+ - spec/models/get_account_posts200_response_posts_inner_spec.rb
6479
6486
  - spec/models/delete_inbox_review_reply200_response_spec.rb
6480
6487
  - spec/models/get_google_business_performance200_response_date_range_spec.rb
6481
6488
  - spec/models/instagram_demographics_response_spec.rb
@@ -6614,6 +6621,7 @@ test_files:
6614
6621
  - spec/models/create_custom_conversion_request_spec.rb
6615
6622
  - spec/models/reply_to_phone_number_reviewer_request_spec.rb
6616
6623
  - spec/models/list_snapchat_profiles200_response_public_profiles_inner_spec.rb
6624
+ - spec/models/get_account_posts200_response_spec.rb
6617
6625
  - spec/models/review_webhook_review_spec.rb
6618
6626
  - spec/models/usage_metering_spec.rb
6619
6627
  - spec/models/validate_subreddit200_response_one_of1_spec.rb