late-sdk 0.0.891 → 0.0.893
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 +1 -2
- data/docs/AnalyticsApi.md +1 -1
- data/docs/{Conversation.md → InboxWebhookConversationDetail.md} +2 -2
- data/docs/WebhookPayloadConversationControlChanged.md +1 -1
- data/docs/WebhookPayloadConversationStarted.md +1 -1
- data/lib/zernio-sdk/api/analytics_api.rb +2 -2
- data/lib/zernio-sdk/models/{conversation.rb → inbox_webhook_conversation_detail.rb} +4 -3
- data/lib/zernio-sdk/models/webhook_payload_conversation_control_changed.rb +1 -1
- data/lib/zernio-sdk/models/webhook_payload_conversation_started.rb +1 -1
- data/lib/zernio-sdk/version.rb +1 -1
- data/lib/zernio-sdk.rb +1 -2
- data/openapi.yaml +42 -35
- data/spec/api/analytics_api_spec.rb +1 -1
- data/spec/models/{conversation_spec.rb → inbox_webhook_conversation_detail_spec.rb} +6 -6
- data/zernio-sdk-0.0.893.gem +0 -0
- metadata +6 -10
- data/docs/WebhookPayloadConversationStartedConversation.md +0 -34
- data/lib/zernio-sdk/models/webhook_payload_conversation_started_conversation.rb +0 -334
- data/spec/models/webhook_payload_conversation_started_conversation_spec.rb +0 -92
- data/zernio-sdk-0.0.891.gem +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5fd86ce35443db934013c4d93c88919a14e76e18b33a8840e77b66df3e2b37c5
|
|
4
|
+
data.tar.gz: 6acff42012ff43c583b90aec95d96c1f478b718b824ffc27f3c77bf62f4e2f3f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 79779669ded9119cee41725c590efdbc831ae40170b90ac51b007fe41e0510608942835ee39817cad5ba68cd2fab60a8cd09c4404d4378d061194f710fcaed99
|
|
7
|
+
data.tar.gz: ee18055cb92d12bf2b1d1845f9e0f5f50777a6649156a2f030bb25c5f4d2451296567366fdd95f18c5d07eed27adcbb025e65129498b1695d863bd2933862981
|
data/README.md
CHANGED
|
@@ -979,7 +979,6 @@ Class | Method | HTTP request | Description
|
|
|
979
979
|
- [Zernio::Connected](docs/Connected.md)
|
|
980
980
|
- [Zernio::ConnectedAccount](docs/ConnectedAccount.md)
|
|
981
981
|
- [Zernio::ConnectedApp](docs/ConnectedApp.md)
|
|
982
|
-
- [Zernio::Conversation](docs/Conversation.md)
|
|
983
982
|
- [Zernio::ConversionAction](docs/ConversionAction.md)
|
|
984
983
|
- [Zernio::ConversionActionTagSnippetsInner](docs/ConversionActionTagSnippetsInner.md)
|
|
985
984
|
- [Zernio::ConversionDestination](docs/ConversionDestination.md)
|
|
@@ -1655,6 +1654,7 @@ Class | Method | HTTP request | Description
|
|
|
1655
1654
|
- [Zernio::InboxMessageEditHistoryEntry](docs/InboxMessageEditHistoryEntry.md)
|
|
1656
1655
|
- [Zernio::InboxWebhookAccount](docs/InboxWebhookAccount.md)
|
|
1657
1656
|
- [Zernio::InboxWebhookConversation](docs/InboxWebhookConversation.md)
|
|
1657
|
+
- [Zernio::InboxWebhookConversationDetail](docs/InboxWebhookConversationDetail.md)
|
|
1658
1658
|
- [Zernio::InboxWebhookMessage](docs/InboxWebhookMessage.md)
|
|
1659
1659
|
- [Zernio::InboxWebhookMessageAttachmentsInner](docs/InboxWebhookMessageAttachmentsInner.md)
|
|
1660
1660
|
- [Zernio::InboxWebhookMessageSender](docs/InboxWebhookMessageSender.md)
|
|
@@ -2569,7 +2569,6 @@ Class | Method | HTTP request | Description
|
|
|
2569
2569
|
- [Zernio::WebhookPayloadConversationControlChanged](docs/WebhookPayloadConversationControlChanged.md)
|
|
2570
2570
|
- [Zernio::WebhookPayloadConversationControlChangedControl](docs/WebhookPayloadConversationControlChangedControl.md)
|
|
2571
2571
|
- [Zernio::WebhookPayloadConversationStarted](docs/WebhookPayloadConversationStarted.md)
|
|
2572
|
-
- [Zernio::WebhookPayloadConversationStartedConversation](docs/WebhookPayloadConversationStartedConversation.md)
|
|
2573
2572
|
- [Zernio::WebhookPayloadExternalPost](docs/WebhookPayloadExternalPost.md)
|
|
2574
2573
|
- [Zernio::WebhookPayloadLead](docs/WebhookPayloadLead.md)
|
|
2575
2574
|
- [Zernio::WebhookPayloadLeadAccount](docs/WebhookPayloadLeadAccount.md)
|
data/docs/AnalyticsApi.md
CHANGED
|
@@ -129,7 +129,7 @@ end
|
|
|
129
129
|
|
|
130
130
|
Analytics changed since a cursor
|
|
131
131
|
|
|
132
|
-
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.**
|
|
132
|
+
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.** Take the cursor FIRST: call this endpoint with NO `cursor` and it answers with an empty `data` array plus the feed's current position in `nextCursor`. Then load your baseline from `GET /v1/analytics`, the historical endpoint, because this one is a rolling 7-day change log and cannot replay history. Then resume from the cursor you took before the baseline. Taking the cursor afterwards instead drops every change that lands while the baseline is loading: it is in neither the row you already read nor the feed you resume behind it. The overlap this order creates is safe, because metrics are absolute values rather than increments, so draining it leaves every post on its newest value. `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 last 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 the same way you bootstrapped: take a fresh cursor from a call to this endpoint with no `cursor`, then re-load from `GET /v1/analytics`, then resume from that 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.
|
|
133
133
|
|
|
134
134
|
### Examples
|
|
135
135
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Zernio::
|
|
1
|
+
# Zernio::InboxWebhookConversationDetail
|
|
2
2
|
|
|
3
3
|
## Properties
|
|
4
4
|
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
```ruby
|
|
20
20
|
require 'zernio-sdk'
|
|
21
21
|
|
|
22
|
-
instance = Zernio::
|
|
22
|
+
instance = Zernio::InboxWebhookConversationDetail.new(
|
|
23
23
|
id: null,
|
|
24
24
|
platform: null,
|
|
25
25
|
platform_conversation_id: null,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
| ---- | ---- | ----------- | ----- |
|
|
7
7
|
| **id** | **String** | Stable webhook event ID | |
|
|
8
8
|
| **event** | **String** | | |
|
|
9
|
-
| **conversation** | [**
|
|
9
|
+
| **conversation** | [**InboxWebhookConversationDetail**](InboxWebhookConversationDetail.md) | | |
|
|
10
10
|
| **account** | [**InboxWebhookAccount**](InboxWebhookAccount.md) | | |
|
|
11
11
|
| **control** | [**WebhookPayloadConversationControlChangedControl**](WebhookPayloadConversationControlChangedControl.md) | | |
|
|
12
12
|
| **changed_at** | **Time** | | |
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
| ---- | ---- | ----------- | ----- |
|
|
7
7
|
| **id** | **String** | Stable webhook event ID | |
|
|
8
8
|
| **event** | **String** | | |
|
|
9
|
-
| **conversation** | [**
|
|
9
|
+
| **conversation** | [**InboxWebhookConversationDetail**](InboxWebhookConversationDetail.md) | | |
|
|
10
10
|
| **account** | [**InboxWebhookAccount**](InboxWebhookAccount.md) | | |
|
|
11
11
|
| **started_at** | **Time** | When the conversation document was created. | |
|
|
12
12
|
| **timestamp** | **Time** | 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. | |
|
|
@@ -134,7 +134,7 @@ module Zernio
|
|
|
134
134
|
end
|
|
135
135
|
|
|
136
136
|
# Analytics changed since a cursor
|
|
137
|
-
# 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.**
|
|
137
|
+
# 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.** Take the cursor FIRST: call this endpoint with NO `cursor` and it answers with an empty `data` array plus the feed's current position in `nextCursor`. Then load your baseline from `GET /v1/analytics`, the historical endpoint, because this one is a rolling 7-day change log and cannot replay history. Then resume from the cursor you took before the baseline. Taking the cursor afterwards instead drops every change that lands while the baseline is loading: it is in neither the row you already read nor the feed you resume behind it. The overlap this order creates is safe, because metrics are absolute values rather than increments, so draining it leaves every post on its newest value. `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 last 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 the same way you bootstrapped: take a fresh cursor from a call to this endpoint with no `cursor`, then re-load from `GET /v1/analytics`, then resume from that 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.
|
|
138
138
|
# @param [Hash] opts the optional parameters
|
|
139
139
|
# @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.
|
|
140
140
|
# @option opts [Integer] :limit Page size. Out-of-range values are a 400, never a silent clamp. (default to 50)
|
|
@@ -147,7 +147,7 @@ module Zernio
|
|
|
147
147
|
end
|
|
148
148
|
|
|
149
149
|
# Analytics changed since a cursor
|
|
150
|
-
# 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.**
|
|
150
|
+
# 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.** Take the cursor FIRST: call this endpoint with NO `cursor` and it answers with an empty `data` array plus the feed's current position in `nextCursor`. Then load your baseline from `GET /v1/analytics`, the historical endpoint, because this one is a rolling 7-day change log and cannot replay history. Then resume from the cursor you took before the baseline. Taking the cursor afterwards instead drops every change that lands while the baseline is loading: it is in neither the row you already read nor the feed you resume behind it. The overlap this order creates is safe, because metrics are absolute values rather than increments, so draining it leaves every post on its newest value. `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 last 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 the same way you bootstrapped: take a fresh cursor from a call to this endpoint with no `cursor`, then re-load from `GET /v1/analytics`, then resume from that 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.
|
|
151
151
|
# @param [Hash] opts the optional parameters
|
|
152
152
|
# @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.
|
|
153
153
|
# @option opts [Integer] :limit Page size. Out-of-range values are a 400, never a silent clamp. (default to 50)
|
|
@@ -14,7 +14,8 @@ require 'date'
|
|
|
14
14
|
require 'time'
|
|
15
15
|
|
|
16
16
|
module Zernio
|
|
17
|
-
|
|
17
|
+
# The conversation object included in conversation lifecycle webhook payloads (conversation.started, conversation.control_changed).
|
|
18
|
+
class InboxWebhookConversationDetail < ApiModelBase
|
|
18
19
|
# Internal conversation ID
|
|
19
20
|
attr_accessor :id
|
|
20
21
|
|
|
@@ -109,14 +110,14 @@ module Zernio
|
|
|
109
110
|
# @param [Hash] attributes Model attributes in the form of hash
|
|
110
111
|
def initialize(attributes = {})
|
|
111
112
|
if (!attributes.is_a?(Hash))
|
|
112
|
-
fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::
|
|
113
|
+
fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::InboxWebhookConversationDetail` initialize method"
|
|
113
114
|
end
|
|
114
115
|
|
|
115
116
|
# check to see if the attribute exists and convert string to symbol for hash key
|
|
116
117
|
acceptable_attribute_map = self.class.acceptable_attribute_map
|
|
117
118
|
attributes = attributes.each_with_object({}) { |(k, v), h|
|
|
118
119
|
if (!acceptable_attribute_map.key?(k.to_sym))
|
|
119
|
-
fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::
|
|
120
|
+
fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::InboxWebhookConversationDetail`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
|
|
120
121
|
end
|
|
121
122
|
h[k.to_sym] = v
|
|
122
123
|
}
|
|
@@ -82,7 +82,7 @@ module Zernio
|
|
|
82
82
|
{
|
|
83
83
|
:'id' => :'String',
|
|
84
84
|
:'event' => :'String',
|
|
85
|
-
:'conversation' => :'
|
|
85
|
+
:'conversation' => :'InboxWebhookConversationDetail',
|
|
86
86
|
:'account' => :'InboxWebhookAccount',
|
|
87
87
|
:'control' => :'WebhookPayloadConversationControlChangedControl',
|
|
88
88
|
:'changed_at' => :'Time',
|
|
@@ -80,7 +80,7 @@ module Zernio
|
|
|
80
80
|
{
|
|
81
81
|
:'id' => :'String',
|
|
82
82
|
:'event' => :'String',
|
|
83
|
-
:'conversation' => :'
|
|
83
|
+
:'conversation' => :'InboxWebhookConversationDetail',
|
|
84
84
|
:'account' => :'InboxWebhookAccount',
|
|
85
85
|
:'started_at' => :'Time',
|
|
86
86
|
:'timestamp' => :'Time'
|
data/lib/zernio-sdk/version.rb
CHANGED
data/lib/zernio-sdk.rb
CHANGED
|
@@ -238,7 +238,6 @@ require 'zernio-sdk/models/connect_whats_app_embedded_signup_request'
|
|
|
238
238
|
require 'zernio-sdk/models/connected'
|
|
239
239
|
require 'zernio-sdk/models/connected_account'
|
|
240
240
|
require 'zernio-sdk/models/connected_app'
|
|
241
|
-
require 'zernio-sdk/models/conversation'
|
|
242
241
|
require 'zernio-sdk/models/conversion_action'
|
|
243
242
|
require 'zernio-sdk/models/conversion_action_tag_snippets_inner'
|
|
244
243
|
require 'zernio-sdk/models/conversion_destination'
|
|
@@ -914,6 +913,7 @@ require 'zernio-sdk/models/inbox_message_edit_attachment'
|
|
|
914
913
|
require 'zernio-sdk/models/inbox_message_edit_history_entry'
|
|
915
914
|
require 'zernio-sdk/models/inbox_webhook_account'
|
|
916
915
|
require 'zernio-sdk/models/inbox_webhook_conversation'
|
|
916
|
+
require 'zernio-sdk/models/inbox_webhook_conversation_detail'
|
|
917
917
|
require 'zernio-sdk/models/inbox_webhook_message'
|
|
918
918
|
require 'zernio-sdk/models/inbox_webhook_message_attachments_inner'
|
|
919
919
|
require 'zernio-sdk/models/inbox_webhook_message_sender'
|
|
@@ -1828,7 +1828,6 @@ require 'zernio-sdk/models/webhook_payload_comment_post'
|
|
|
1828
1828
|
require 'zernio-sdk/models/webhook_payload_conversation_control_changed'
|
|
1829
1829
|
require 'zernio-sdk/models/webhook_payload_conversation_control_changed_control'
|
|
1830
1830
|
require 'zernio-sdk/models/webhook_payload_conversation_started'
|
|
1831
|
-
require 'zernio-sdk/models/webhook_payload_conversation_started_conversation'
|
|
1832
1831
|
require 'zernio-sdk/models/webhook_payload_external_post'
|
|
1833
1832
|
require 'zernio-sdk/models/webhook_payload_lead'
|
|
1834
1833
|
require 'zernio-sdk/models/webhook_payload_lead_account'
|
data/openapi.yaml
CHANGED
|
@@ -3599,6 +3599,32 @@ components:
|
|
|
3599
3599
|
integrators join any inbox webhook back to the CRM Contact without
|
|
3600
3600
|
needing to look at the sender, which matters for outgoing and
|
|
3601
3601
|
delivery-status events whose sender is the business.
|
|
3602
|
+
InboxWebhookConversationDetail:
|
|
3603
|
+
type: object
|
|
3604
|
+
description: The conversation object included in conversation lifecycle webhook payloads (conversation.started, conversation.control_changed).
|
|
3605
|
+
required: [id, platform, platformConversationId, participantName, status]
|
|
3606
|
+
properties:
|
|
3607
|
+
id: { type: string, description: Internal conversation ID }
|
|
3608
|
+
platform:
|
|
3609
|
+
type: string
|
|
3610
|
+
enum: [instagram, facebook, telegram, whatsapp, twitter, reddit, bluesky, sms, slack]
|
|
3611
|
+
platformConversationId: { type: string }
|
|
3612
|
+
participantId: { type: string, description: "Contact's platform identifier (IGSID, PSID, wa_id, etc.)" }
|
|
3613
|
+
participantName: { type: string }
|
|
3614
|
+
participantUsername: { type: string, description: Contact's handle when the platform exposes one }
|
|
3615
|
+
participantPicture: { type: string }
|
|
3616
|
+
status:
|
|
3617
|
+
type: string
|
|
3618
|
+
enum: [active, archived]
|
|
3619
|
+
contactId:
|
|
3620
|
+
type: string
|
|
3621
|
+
description: |
|
|
3622
|
+
Zernio CRM Contact ID for the participant, when one exists. Resolved by
|
|
3623
|
+
joining `participantId` to the ContactChannel collection (same join
|
|
3624
|
+
used by message.*, reaction.received, and call.* webhooks). Best-effort:
|
|
3625
|
+
omitted when no channel matches or `participantId` is absent. Lets
|
|
3626
|
+
integrators seed the CRM straight from `conversation.started` without
|
|
3627
|
+
waiting for the first `message.*` event.
|
|
3602
3628
|
InboxWebhookAccount:
|
|
3603
3629
|
type: object
|
|
3604
3630
|
description: The account context included in inbox webhook payloads.
|
|
@@ -4518,30 +4544,7 @@ components:
|
|
|
4518
4544
|
type: string
|
|
4519
4545
|
enum: [conversation.started]
|
|
4520
4546
|
conversation:
|
|
4521
|
-
|
|
4522
|
-
required: [id, platform, platformConversationId, participantName, status]
|
|
4523
|
-
properties:
|
|
4524
|
-
id: { type: string, description: Internal conversation ID }
|
|
4525
|
-
platform:
|
|
4526
|
-
type: string
|
|
4527
|
-
enum: [instagram, facebook, telegram, whatsapp, twitter, reddit, bluesky, sms, slack]
|
|
4528
|
-
platformConversationId: { type: string }
|
|
4529
|
-
participantId: { type: string, description: "Contact's platform identifier (IGSID, PSID, wa_id, etc.)" }
|
|
4530
|
-
participantName: { type: string }
|
|
4531
|
-
participantUsername: { type: string, description: Contact's handle when the platform exposes one }
|
|
4532
|
-
participantPicture: { type: string }
|
|
4533
|
-
status:
|
|
4534
|
-
type: string
|
|
4535
|
-
enum: [active, archived]
|
|
4536
|
-
contactId:
|
|
4537
|
-
type: string
|
|
4538
|
-
description: |
|
|
4539
|
-
Zernio CRM Contact ID for the participant, when one exists. Resolved by
|
|
4540
|
-
joining `participantId` to the ContactChannel collection (same join
|
|
4541
|
-
used by message.*, reaction.received, and call.* webhooks). Best-effort:
|
|
4542
|
-
omitted when no channel matches or `participantId` is absent. Lets
|
|
4543
|
-
integrators seed the CRM straight from `conversation.started` without
|
|
4544
|
-
waiting for the first `message.*` event.
|
|
4547
|
+
$ref: '#/components/schemas/InboxWebhookConversationDetail'
|
|
4545
4548
|
account:
|
|
4546
4549
|
$ref: '#/components/schemas/InboxWebhookAccount'
|
|
4547
4550
|
startedAt:
|
|
@@ -4564,7 +4567,7 @@ components:
|
|
|
4564
4567
|
type: string
|
|
4565
4568
|
enum: [conversation.control_changed]
|
|
4566
4569
|
conversation:
|
|
4567
|
-
$ref: '#/components/schemas/
|
|
4570
|
+
$ref: '#/components/schemas/InboxWebhookConversationDetail'
|
|
4568
4571
|
account:
|
|
4569
4572
|
$ref: '#/components/schemas/InboxWebhookAccount'
|
|
4570
4573
|
control:
|
|
@@ -11778,13 +11781,17 @@ paths:
|
|
|
11778
11781
|
1,600 connected accounts: about 1,599 per-account analytics calls an hour became
|
|
11779
11782
|
about 205 delta calls an hour, a 7.8x reduction.
|
|
11780
11783
|
|
|
11781
|
-
**Bootstrap once, then stay in sync.**
|
|
11782
|
-
`
|
|
11783
|
-
|
|
11784
|
-
|
|
11785
|
-
|
|
11786
|
-
|
|
11787
|
-
|
|
11784
|
+
**Bootstrap once, then stay in sync.** Take the cursor FIRST: call this endpoint
|
|
11785
|
+
with NO `cursor` and it answers with an empty `data` array plus the feed's current
|
|
11786
|
+
position in `nextCursor`. Then load your baseline from `GET /v1/analytics`, the
|
|
11787
|
+
historical endpoint, because this one is a rolling 7-day change log and cannot
|
|
11788
|
+
replay history. Then resume from the cursor you took before the baseline. Taking
|
|
11789
|
+
the cursor afterwards instead drops every change that lands while the baseline is
|
|
11790
|
+
loading: it is in neither the row you already read nor the feed you resume behind
|
|
11791
|
+
it. The overlap this order creates is safe, because metrics are absolute values
|
|
11792
|
+
rather than increments, so draining it leaves every post on its newest value.
|
|
11793
|
+
`nextCursor` is present on every response, empty pages included, so you always
|
|
11794
|
+
have something to advance with.
|
|
11788
11795
|
|
|
11789
11796
|
**Ordering.** Entries come back oldest first, in the order the feed received
|
|
11790
11797
|
them. That order is NOT `syncedAt`: `syncedAt` is stamped when an account's sync
|
|
@@ -11814,9 +11821,9 @@ paths:
|
|
|
11814
11821
|
|
|
11815
11822
|
**Retention is 7 days.** Changes older than that leave the feed. A cursor older
|
|
11816
11823
|
than 6 days is rejected with a `400` (a day of margin, because expiry is lazy).
|
|
11817
|
-
Recover
|
|
11818
|
-
|
|
11819
|
-
daily never reaches this.
|
|
11824
|
+
Recover the same way you bootstrapped: take a fresh cursor from a call to this
|
|
11825
|
+
endpoint with no `cursor`, then re-load from `GET /v1/analytics`, then resume
|
|
11826
|
+
from that cursor. A consumer that polls at least daily never reaches this.
|
|
11820
11827
|
|
|
11821
11828
|
Pairs with the `analytics.synced` webhook, so changes can be read on notification
|
|
11822
11829
|
instead of on a timer. That event carries no cursor of its own: keep using the
|
|
@@ -56,7 +56,7 @@ describe 'AnalyticsApi' do
|
|
|
56
56
|
|
|
57
57
|
# unit tests for get_analytics_delta
|
|
58
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.**
|
|
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.** Take the cursor FIRST: call this endpoint with NO `cursor` and it answers with an empty `data` array plus the feed's current position in `nextCursor`. Then load your baseline from `GET /v1/analytics`, the historical endpoint, because this one is a rolling 7-day change log and cannot replay history. Then resume from the cursor you took before the baseline. Taking the cursor afterwards instead drops every change that lands while the baseline is loading: it is in neither the row you already read nor the feed you resume behind it. The overlap this order creates is safe, because metrics are absolute values rather than increments, so draining it leaves every post on its newest value. `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 last 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 the same way you bootstrapped: take a fresh cursor from a call to this endpoint with no `cursor`, then re-load from `GET /v1/analytics`, then resume from that 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
60
|
# @param [Hash] opts the optional parameters
|
|
61
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
62
|
# @option opts [Integer] :limit Page size. Out-of-range values are a 400, never a silent clamp.
|
|
@@ -14,16 +14,16 @@ require 'spec_helper'
|
|
|
14
14
|
require 'json'
|
|
15
15
|
require 'date'
|
|
16
16
|
|
|
17
|
-
# Unit tests for Zernio::
|
|
17
|
+
# Unit tests for Zernio::InboxWebhookConversationDetail
|
|
18
18
|
# Automatically generated by openapi-generator (https://openapi-generator.tech)
|
|
19
19
|
# Please update as you see appropriate
|
|
20
|
-
describe Zernio::
|
|
21
|
-
#let(:instance) { Zernio::
|
|
20
|
+
describe Zernio::InboxWebhookConversationDetail do
|
|
21
|
+
#let(:instance) { Zernio::InboxWebhookConversationDetail.new }
|
|
22
22
|
|
|
23
|
-
describe 'test an instance of
|
|
24
|
-
it 'should create an instance of
|
|
23
|
+
describe 'test an instance of InboxWebhookConversationDetail' do
|
|
24
|
+
it 'should create an instance of InboxWebhookConversationDetail' do
|
|
25
25
|
# uncomment below to test the instance creation
|
|
26
|
-
#expect(instance).to be_instance_of(Zernio::
|
|
26
|
+
#expect(instance).to be_instance_of(Zernio::InboxWebhookConversationDetail)
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: late-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.893
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- OpenAPI-Generator
|
|
@@ -309,7 +309,6 @@ files:
|
|
|
309
309
|
- docs/ConnectedApp.md
|
|
310
310
|
- docs/ConnectedAppsApi.md
|
|
311
311
|
- docs/ContactsApi.md
|
|
312
|
-
- docs/Conversation.md
|
|
313
312
|
- docs/ConversionAction.md
|
|
314
313
|
- docs/ConversionActionTagSnippetsInner.md
|
|
315
314
|
- docs/ConversionDestination.md
|
|
@@ -997,6 +996,7 @@ files:
|
|
|
997
996
|
- docs/InboxMessageEditHistoryEntry.md
|
|
998
997
|
- docs/InboxWebhookAccount.md
|
|
999
998
|
- docs/InboxWebhookConversation.md
|
|
999
|
+
- docs/InboxWebhookConversationDetail.md
|
|
1000
1000
|
- docs/InboxWebhookMessage.md
|
|
1001
1001
|
- docs/InboxWebhookMessageAttachmentsInner.md
|
|
1002
1002
|
- docs/InboxWebhookMessageSender.md
|
|
@@ -1938,7 +1938,6 @@ files:
|
|
|
1938
1938
|
- docs/WebhookPayloadConversationControlChanged.md
|
|
1939
1939
|
- docs/WebhookPayloadConversationControlChangedControl.md
|
|
1940
1940
|
- docs/WebhookPayloadConversationStarted.md
|
|
1941
|
-
- docs/WebhookPayloadConversationStartedConversation.md
|
|
1942
1941
|
- docs/WebhookPayloadExternalPost.md
|
|
1943
1942
|
- docs/WebhookPayloadLead.md
|
|
1944
1943
|
- docs/WebhookPayloadLeadAccount.md
|
|
@@ -2360,7 +2359,6 @@ files:
|
|
|
2360
2359
|
- lib/zernio-sdk/models/connected.rb
|
|
2361
2360
|
- lib/zernio-sdk/models/connected_account.rb
|
|
2362
2361
|
- lib/zernio-sdk/models/connected_app.rb
|
|
2363
|
-
- lib/zernio-sdk/models/conversation.rb
|
|
2364
2362
|
- lib/zernio-sdk/models/conversion_action.rb
|
|
2365
2363
|
- lib/zernio-sdk/models/conversion_action_tag_snippets_inner.rb
|
|
2366
2364
|
- lib/zernio-sdk/models/conversion_destination.rb
|
|
@@ -3036,6 +3034,7 @@ files:
|
|
|
3036
3034
|
- lib/zernio-sdk/models/inbox_message_edit_history_entry.rb
|
|
3037
3035
|
- lib/zernio-sdk/models/inbox_webhook_account.rb
|
|
3038
3036
|
- lib/zernio-sdk/models/inbox_webhook_conversation.rb
|
|
3037
|
+
- lib/zernio-sdk/models/inbox_webhook_conversation_detail.rb
|
|
3039
3038
|
- lib/zernio-sdk/models/inbox_webhook_message.rb
|
|
3040
3039
|
- lib/zernio-sdk/models/inbox_webhook_message_attachments_inner.rb
|
|
3041
3040
|
- lib/zernio-sdk/models/inbox_webhook_message_sender.rb
|
|
@@ -3950,7 +3949,6 @@ files:
|
|
|
3950
3949
|
- lib/zernio-sdk/models/webhook_payload_conversation_control_changed.rb
|
|
3951
3950
|
- lib/zernio-sdk/models/webhook_payload_conversation_control_changed_control.rb
|
|
3952
3951
|
- lib/zernio-sdk/models/webhook_payload_conversation_started.rb
|
|
3953
|
-
- lib/zernio-sdk/models/webhook_payload_conversation_started_conversation.rb
|
|
3954
3952
|
- lib/zernio-sdk/models/webhook_payload_external_post.rb
|
|
3955
3953
|
- lib/zernio-sdk/models/webhook_payload_lead.rb
|
|
3956
3954
|
- lib/zernio-sdk/models/webhook_payload_lead_account.rb
|
|
@@ -4358,7 +4356,6 @@ files:
|
|
|
4358
4356
|
- spec/models/connected_account_spec.rb
|
|
4359
4357
|
- spec/models/connected_app_spec.rb
|
|
4360
4358
|
- spec/models/connected_spec.rb
|
|
4361
|
-
- spec/models/conversation_spec.rb
|
|
4362
4359
|
- spec/models/conversion_action_spec.rb
|
|
4363
4360
|
- spec/models/conversion_action_tag_snippets_inner_spec.rb
|
|
4364
4361
|
- spec/models/conversion_destination_spec.rb
|
|
@@ -5033,6 +5030,7 @@ files:
|
|
|
5033
5030
|
- spec/models/inbox_message_edit_attachment_spec.rb
|
|
5034
5031
|
- spec/models/inbox_message_edit_history_entry_spec.rb
|
|
5035
5032
|
- spec/models/inbox_webhook_account_spec.rb
|
|
5033
|
+
- spec/models/inbox_webhook_conversation_detail_spec.rb
|
|
5036
5034
|
- spec/models/inbox_webhook_conversation_spec.rb
|
|
5037
5035
|
- spec/models/inbox_webhook_message_attachments_inner_spec.rb
|
|
5038
5036
|
- spec/models/inbox_webhook_message_sender_instagram_profile_spec.rb
|
|
@@ -5946,7 +5944,6 @@ files:
|
|
|
5946
5944
|
- spec/models/webhook_payload_comment_spec.rb
|
|
5947
5945
|
- spec/models/webhook_payload_conversation_control_changed_control_spec.rb
|
|
5948
5946
|
- spec/models/webhook_payload_conversation_control_changed_spec.rb
|
|
5949
|
-
- spec/models/webhook_payload_conversation_started_conversation_spec.rb
|
|
5950
5947
|
- spec/models/webhook_payload_conversation_started_spec.rb
|
|
5951
5948
|
- spec/models/webhook_payload_external_post_spec.rb
|
|
5952
5949
|
- spec/models/webhook_payload_lead_account_spec.rb
|
|
@@ -6067,7 +6064,7 @@ files:
|
|
|
6067
6064
|
- spec/models/you_tube_video_retention_response_retention_curve_inner_spec.rb
|
|
6068
6065
|
- spec/models/you_tube_video_retention_response_spec.rb
|
|
6069
6066
|
- spec/spec_helper.rb
|
|
6070
|
-
- zernio-sdk-0.0.
|
|
6067
|
+
- zernio-sdk-0.0.893.gem
|
|
6071
6068
|
- zernio-sdk.gemspec
|
|
6072
6069
|
homepage: https://openapi-generator.tech
|
|
6073
6070
|
licenses:
|
|
@@ -6941,7 +6938,6 @@ test_files:
|
|
|
6941
6938
|
- spec/models/list_inbox_conversation_analytics200_response_spec.rb
|
|
6942
6939
|
- spec/models/targeting_spec_excluded_locations_places_inner_spec.rb
|
|
6943
6940
|
- spec/models/list_high_demand_periods200_response_spec.rb
|
|
6944
|
-
- spec/models/conversation_spec.rb
|
|
6945
6941
|
- spec/models/create_voice_call200_response_spec.rb
|
|
6946
6942
|
- spec/models/create_standalone_ad_request_dynamic_creative_spec.rb
|
|
6947
6943
|
- spec/models/inbox_webhook_message_sender_instagram_profile_spec.rb
|
|
@@ -7751,6 +7747,7 @@ test_files:
|
|
|
7751
7747
|
- spec/models/get_whats_app_sdk_config200_response_spec.rb
|
|
7752
7748
|
- spec/models/whats_app_carousel_component_cards_inner_spec.rb
|
|
7753
7749
|
- spec/models/get_inbox_conversation_messages200_response_messages_inner_attachments_inner_spec.rb
|
|
7750
|
+
- spec/models/inbox_webhook_conversation_detail_spec.rb
|
|
7754
7751
|
- spec/models/validate_post_request_spec.rb
|
|
7755
7752
|
- spec/models/list_users200_response_spec.rb
|
|
7756
7753
|
- spec/models/ad_keyword_metrics_spec.rb
|
|
@@ -8023,7 +8020,6 @@ test_files:
|
|
|
8023
8020
|
- spec/models/webhook_payload_call_received_spec.rb
|
|
8024
8021
|
- spec/models/update_discord_settings200_response_account_spec.rb
|
|
8025
8022
|
- spec/models/get_whats_app_business_profile200_response_spec.rb
|
|
8026
|
-
- spec/models/webhook_payload_conversation_started_conversation_spec.rb
|
|
8027
8023
|
- spec/models/get_inbox_conversation_messages200_response_spec.rb
|
|
8028
8024
|
- spec/models/get_google_business_reviews200_response_spec.rb
|
|
8029
8025
|
- spec/models/list_whats_app_flow_versions200_response_spec.rb
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# Zernio::WebhookPayloadConversationStartedConversation
|
|
2
|
-
|
|
3
|
-
## Properties
|
|
4
|
-
|
|
5
|
-
| Name | Type | Description | Notes |
|
|
6
|
-
| ---- | ---- | ----------- | ----- |
|
|
7
|
-
| **id** | **String** | Internal conversation ID | |
|
|
8
|
-
| **platform** | **String** | | |
|
|
9
|
-
| **platform_conversation_id** | **String** | | |
|
|
10
|
-
| **participant_id** | **String** | Contact's platform identifier (IGSID, PSID, wa_id, etc.) | [optional] |
|
|
11
|
-
| **participant_name** | **String** | | |
|
|
12
|
-
| **participant_username** | **String** | Contact's handle when the platform exposes one | [optional] |
|
|
13
|
-
| **participant_picture** | **String** | | [optional] |
|
|
14
|
-
| **status** | **String** | | |
|
|
15
|
-
| **contact_id** | **String** | Zernio CRM Contact ID for the participant, when one exists. Resolved by joining `participantId` to the ContactChannel collection (same join used by message.*, reaction.received, and call.* webhooks). Best-effort: omitted when no channel matches or `participantId` is absent. Lets integrators seed the CRM straight from `conversation.started` without waiting for the first `message.*` event. | [optional] |
|
|
16
|
-
|
|
17
|
-
## Example
|
|
18
|
-
|
|
19
|
-
```ruby
|
|
20
|
-
require 'zernio-sdk'
|
|
21
|
-
|
|
22
|
-
instance = Zernio::WebhookPayloadConversationStartedConversation.new(
|
|
23
|
-
id: null,
|
|
24
|
-
platform: null,
|
|
25
|
-
platform_conversation_id: null,
|
|
26
|
-
participant_id: null,
|
|
27
|
-
participant_name: null,
|
|
28
|
-
participant_username: null,
|
|
29
|
-
participant_picture: null,
|
|
30
|
-
status: null,
|
|
31
|
-
contact_id: null
|
|
32
|
-
)
|
|
33
|
-
```
|
|
34
|
-
|
|
@@ -1,334 +0,0 @@
|
|
|
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 WebhookPayloadConversationStartedConversation < ApiModelBase
|
|
18
|
-
# Internal conversation ID
|
|
19
|
-
attr_accessor :id
|
|
20
|
-
|
|
21
|
-
attr_accessor :platform
|
|
22
|
-
|
|
23
|
-
attr_accessor :platform_conversation_id
|
|
24
|
-
|
|
25
|
-
# Contact's platform identifier (IGSID, PSID, wa_id, etc.)
|
|
26
|
-
attr_accessor :participant_id
|
|
27
|
-
|
|
28
|
-
attr_accessor :participant_name
|
|
29
|
-
|
|
30
|
-
# Contact's handle when the platform exposes one
|
|
31
|
-
attr_accessor :participant_username
|
|
32
|
-
|
|
33
|
-
attr_accessor :participant_picture
|
|
34
|
-
|
|
35
|
-
attr_accessor :status
|
|
36
|
-
|
|
37
|
-
# Zernio CRM Contact ID for the participant, when one exists. Resolved by joining `participantId` to the ContactChannel collection (same join used by message.*, reaction.received, and call.* webhooks). Best-effort: omitted when no channel matches or `participantId` is absent. Lets integrators seed the CRM straight from `conversation.started` without waiting for the first `message.*` event.
|
|
38
|
-
attr_accessor :contact_id
|
|
39
|
-
|
|
40
|
-
class EnumAttributeValidator
|
|
41
|
-
attr_reader :datatype
|
|
42
|
-
attr_reader :allowable_values
|
|
43
|
-
|
|
44
|
-
def initialize(datatype, allowable_values)
|
|
45
|
-
@allowable_values = allowable_values.map do |value|
|
|
46
|
-
case datatype.to_s
|
|
47
|
-
when /Integer/i
|
|
48
|
-
value.to_i
|
|
49
|
-
when /Float/i
|
|
50
|
-
value.to_f
|
|
51
|
-
else
|
|
52
|
-
value
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def valid?(value)
|
|
58
|
-
!value || allowable_values.include?(value)
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
# Attribute mapping from ruby-style variable name to JSON key.
|
|
63
|
-
def self.attribute_map
|
|
64
|
-
{
|
|
65
|
-
:'id' => :'id',
|
|
66
|
-
:'platform' => :'platform',
|
|
67
|
-
:'platform_conversation_id' => :'platformConversationId',
|
|
68
|
-
:'participant_id' => :'participantId',
|
|
69
|
-
:'participant_name' => :'participantName',
|
|
70
|
-
:'participant_username' => :'participantUsername',
|
|
71
|
-
:'participant_picture' => :'participantPicture',
|
|
72
|
-
:'status' => :'status',
|
|
73
|
-
:'contact_id' => :'contactId'
|
|
74
|
-
}
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# Returns attribute mapping this model knows about
|
|
78
|
-
def self.acceptable_attribute_map
|
|
79
|
-
attribute_map
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# Returns all the JSON keys this model knows about
|
|
83
|
-
def self.acceptable_attributes
|
|
84
|
-
acceptable_attribute_map.values
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# Attribute type mapping.
|
|
88
|
-
def self.openapi_types
|
|
89
|
-
{
|
|
90
|
-
:'id' => :'String',
|
|
91
|
-
:'platform' => :'String',
|
|
92
|
-
:'platform_conversation_id' => :'String',
|
|
93
|
-
:'participant_id' => :'String',
|
|
94
|
-
:'participant_name' => :'String',
|
|
95
|
-
:'participant_username' => :'String',
|
|
96
|
-
:'participant_picture' => :'String',
|
|
97
|
-
:'status' => :'String',
|
|
98
|
-
:'contact_id' => :'String'
|
|
99
|
-
}
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
# List of attributes with nullable: true
|
|
103
|
-
def self.openapi_nullable
|
|
104
|
-
Set.new([
|
|
105
|
-
])
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
# Initializes the object
|
|
109
|
-
# @param [Hash] attributes Model attributes in the form of hash
|
|
110
|
-
def initialize(attributes = {})
|
|
111
|
-
if (!attributes.is_a?(Hash))
|
|
112
|
-
fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::WebhookPayloadConversationStartedConversation` initialize method"
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
# check to see if the attribute exists and convert string to symbol for hash key
|
|
116
|
-
acceptable_attribute_map = self.class.acceptable_attribute_map
|
|
117
|
-
attributes = attributes.each_with_object({}) { |(k, v), h|
|
|
118
|
-
if (!acceptable_attribute_map.key?(k.to_sym))
|
|
119
|
-
fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::WebhookPayloadConversationStartedConversation`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
|
|
120
|
-
end
|
|
121
|
-
h[k.to_sym] = v
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if attributes.key?(:'id')
|
|
125
|
-
self.id = attributes[:'id']
|
|
126
|
-
else
|
|
127
|
-
self.id = nil
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
if attributes.key?(:'platform')
|
|
131
|
-
self.platform = attributes[:'platform']
|
|
132
|
-
else
|
|
133
|
-
self.platform = nil
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
if attributes.key?(:'platform_conversation_id')
|
|
137
|
-
self.platform_conversation_id = attributes[:'platform_conversation_id']
|
|
138
|
-
else
|
|
139
|
-
self.platform_conversation_id = nil
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
if attributes.key?(:'participant_id')
|
|
143
|
-
self.participant_id = attributes[:'participant_id']
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
if attributes.key?(:'participant_name')
|
|
147
|
-
self.participant_name = attributes[:'participant_name']
|
|
148
|
-
else
|
|
149
|
-
self.participant_name = nil
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
if attributes.key?(:'participant_username')
|
|
153
|
-
self.participant_username = attributes[:'participant_username']
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
if attributes.key?(:'participant_picture')
|
|
157
|
-
self.participant_picture = attributes[:'participant_picture']
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
if attributes.key?(:'status')
|
|
161
|
-
self.status = attributes[:'status']
|
|
162
|
-
else
|
|
163
|
-
self.status = nil
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
if attributes.key?(:'contact_id')
|
|
167
|
-
self.contact_id = attributes[:'contact_id']
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
# Show invalid properties with the reasons. Usually used together with valid?
|
|
172
|
-
# @return Array for valid properties with the reasons
|
|
173
|
-
def list_invalid_properties
|
|
174
|
-
warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
|
|
175
|
-
invalid_properties = Array.new
|
|
176
|
-
if @id.nil?
|
|
177
|
-
invalid_properties.push('invalid value for "id", id cannot be nil.')
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
if @platform.nil?
|
|
181
|
-
invalid_properties.push('invalid value for "platform", platform cannot be nil.')
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
if @platform_conversation_id.nil?
|
|
185
|
-
invalid_properties.push('invalid value for "platform_conversation_id", platform_conversation_id cannot be nil.')
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
if @participant_name.nil?
|
|
189
|
-
invalid_properties.push('invalid value for "participant_name", participant_name cannot be nil.')
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
if @status.nil?
|
|
193
|
-
invalid_properties.push('invalid value for "status", status cannot be nil.')
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
invalid_properties
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
# Check to see if the all the properties in the model are valid
|
|
200
|
-
# @return true if the model is valid
|
|
201
|
-
def valid?
|
|
202
|
-
warn '[DEPRECATED] the `valid?` method is obsolete'
|
|
203
|
-
return false if @id.nil?
|
|
204
|
-
return false if @platform.nil?
|
|
205
|
-
platform_validator = EnumAttributeValidator.new('String', ["instagram", "facebook", "telegram", "whatsapp", "twitter", "reddit", "bluesky", "sms", "slack"])
|
|
206
|
-
return false unless platform_validator.valid?(@platform)
|
|
207
|
-
return false if @platform_conversation_id.nil?
|
|
208
|
-
return false if @participant_name.nil?
|
|
209
|
-
return false if @status.nil?
|
|
210
|
-
status_validator = EnumAttributeValidator.new('String', ["active", "archived"])
|
|
211
|
-
return false unless status_validator.valid?(@status)
|
|
212
|
-
true
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
# Custom attribute writer method with validation
|
|
216
|
-
# @param [Object] id Value to be assigned
|
|
217
|
-
def id=(id)
|
|
218
|
-
if id.nil?
|
|
219
|
-
fail ArgumentError, 'id cannot be nil'
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
@id = id
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
# Custom attribute writer method checking allowed values (enum).
|
|
226
|
-
# @param [Object] platform Object to be assigned
|
|
227
|
-
def platform=(platform)
|
|
228
|
-
validator = EnumAttributeValidator.new('String', ["instagram", "facebook", "telegram", "whatsapp", "twitter", "reddit", "bluesky", "sms", "slack"])
|
|
229
|
-
unless validator.valid?(platform)
|
|
230
|
-
fail ArgumentError, "invalid value for \"platform\", must be one of #{validator.allowable_values}."
|
|
231
|
-
end
|
|
232
|
-
@platform = platform
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
# Custom attribute writer method with validation
|
|
236
|
-
# @param [Object] platform_conversation_id Value to be assigned
|
|
237
|
-
def platform_conversation_id=(platform_conversation_id)
|
|
238
|
-
if platform_conversation_id.nil?
|
|
239
|
-
fail ArgumentError, 'platform_conversation_id cannot be nil'
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
@platform_conversation_id = platform_conversation_id
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
# Custom attribute writer method with validation
|
|
246
|
-
# @param [Object] participant_name Value to be assigned
|
|
247
|
-
def participant_name=(participant_name)
|
|
248
|
-
if participant_name.nil?
|
|
249
|
-
fail ArgumentError, 'participant_name cannot be nil'
|
|
250
|
-
end
|
|
251
|
-
|
|
252
|
-
@participant_name = participant_name
|
|
253
|
-
end
|
|
254
|
-
|
|
255
|
-
# Custom attribute writer method checking allowed values (enum).
|
|
256
|
-
# @param [Object] status Object to be assigned
|
|
257
|
-
def status=(status)
|
|
258
|
-
validator = EnumAttributeValidator.new('String', ["active", "archived"])
|
|
259
|
-
unless validator.valid?(status)
|
|
260
|
-
fail ArgumentError, "invalid value for \"status\", must be one of #{validator.allowable_values}."
|
|
261
|
-
end
|
|
262
|
-
@status = status
|
|
263
|
-
end
|
|
264
|
-
|
|
265
|
-
# Checks equality by comparing each attribute.
|
|
266
|
-
# @param [Object] Object to be compared
|
|
267
|
-
def ==(o)
|
|
268
|
-
return true if self.equal?(o)
|
|
269
|
-
self.class == o.class &&
|
|
270
|
-
id == o.id &&
|
|
271
|
-
platform == o.platform &&
|
|
272
|
-
platform_conversation_id == o.platform_conversation_id &&
|
|
273
|
-
participant_id == o.participant_id &&
|
|
274
|
-
participant_name == o.participant_name &&
|
|
275
|
-
participant_username == o.participant_username &&
|
|
276
|
-
participant_picture == o.participant_picture &&
|
|
277
|
-
status == o.status &&
|
|
278
|
-
contact_id == o.contact_id
|
|
279
|
-
end
|
|
280
|
-
|
|
281
|
-
# @see the `==` method
|
|
282
|
-
# @param [Object] Object to be compared
|
|
283
|
-
def eql?(o)
|
|
284
|
-
self == o
|
|
285
|
-
end
|
|
286
|
-
|
|
287
|
-
# Calculates hash code according to all attributes.
|
|
288
|
-
# @return [Integer] Hash code
|
|
289
|
-
def hash
|
|
290
|
-
[id, platform, platform_conversation_id, participant_id, participant_name, participant_username, participant_picture, status, contact_id].hash
|
|
291
|
-
end
|
|
292
|
-
|
|
293
|
-
# Builds the object from hash
|
|
294
|
-
# @param [Hash] attributes Model attributes in the form of hash
|
|
295
|
-
# @return [Object] Returns the model itself
|
|
296
|
-
def self.build_from_hash(attributes)
|
|
297
|
-
return nil unless attributes.is_a?(Hash)
|
|
298
|
-
attributes = attributes.transform_keys(&:to_sym)
|
|
299
|
-
transformed_hash = {}
|
|
300
|
-
openapi_types.each_pair do |key, type|
|
|
301
|
-
if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
|
|
302
|
-
transformed_hash["#{key}"] = nil
|
|
303
|
-
elsif type =~ /\AArray<(.*)>/i
|
|
304
|
-
# check to ensure the input is an array given that the attribute
|
|
305
|
-
# is documented as an array but the input is not
|
|
306
|
-
if attributes[attribute_map[key]].is_a?(Array)
|
|
307
|
-
transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
|
|
308
|
-
end
|
|
309
|
-
elsif !attributes[attribute_map[key]].nil?
|
|
310
|
-
transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
|
|
311
|
-
end
|
|
312
|
-
end
|
|
313
|
-
new(transformed_hash)
|
|
314
|
-
end
|
|
315
|
-
|
|
316
|
-
# Returns the object in the form of hash
|
|
317
|
-
# @return [Hash] Returns the object in the form of hash
|
|
318
|
-
def to_hash
|
|
319
|
-
hash = {}
|
|
320
|
-
self.class.attribute_map.each_pair do |attr, param|
|
|
321
|
-
value = self.send(attr)
|
|
322
|
-
if value.nil?
|
|
323
|
-
is_nullable = self.class.openapi_nullable.include?(attr)
|
|
324
|
-
next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
|
|
325
|
-
end
|
|
326
|
-
|
|
327
|
-
hash[param] = _to_hash(value)
|
|
328
|
-
end
|
|
329
|
-
hash
|
|
330
|
-
end
|
|
331
|
-
|
|
332
|
-
end
|
|
333
|
-
|
|
334
|
-
end
|
|
@@ -1,92 +0,0 @@
|
|
|
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::WebhookPayloadConversationStartedConversation
|
|
18
|
-
# Automatically generated by openapi-generator (https://openapi-generator.tech)
|
|
19
|
-
# Please update as you see appropriate
|
|
20
|
-
describe Zernio::WebhookPayloadConversationStartedConversation do
|
|
21
|
-
#let(:instance) { Zernio::WebhookPayloadConversationStartedConversation.new }
|
|
22
|
-
|
|
23
|
-
describe 'test an instance of WebhookPayloadConversationStartedConversation' do
|
|
24
|
-
it 'should create an instance of WebhookPayloadConversationStartedConversation' do
|
|
25
|
-
# uncomment below to test the instance creation
|
|
26
|
-
#expect(instance).to be_instance_of(Zernio::WebhookPayloadConversationStartedConversation)
|
|
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
|
-
# validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["instagram", "facebook", "telegram", "whatsapp", "twitter", "reddit", "bluesky", "sms", "slack"])
|
|
40
|
-
# validator.allowable_values.each do |value|
|
|
41
|
-
# expect { instance.platform = value }.not_to raise_error
|
|
42
|
-
# end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
describe 'test attribute "platform_conversation_id"' 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
|
-
describe 'test attribute "participant_id"' do
|
|
53
|
-
it 'should work' do
|
|
54
|
-
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
describe 'test attribute "participant_name"' do
|
|
59
|
-
it 'should work' do
|
|
60
|
-
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
describe 'test attribute "participant_username"' do
|
|
65
|
-
it 'should work' do
|
|
66
|
-
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
describe 'test attribute "participant_picture"' do
|
|
71
|
-
it 'should work' do
|
|
72
|
-
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
describe 'test attribute "status"' do
|
|
77
|
-
it 'should work' do
|
|
78
|
-
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
79
|
-
# validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["active", "archived"])
|
|
80
|
-
# validator.allowable_values.each do |value|
|
|
81
|
-
# expect { instance.status = value }.not_to raise_error
|
|
82
|
-
# end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
describe 'test attribute "contact_id"' do
|
|
87
|
-
it 'should work' do
|
|
88
|
-
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
end
|
data/zernio-sdk-0.0.891.gem
DELETED
|
Binary file
|