zernio-sdk 0.0.807 → 0.0.809
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/docs/ConnectApi.md +7 -7
- data/docs/GetInboxConversationMessages200ResponseMessagesInnerAttachmentsInner.md +2 -0
- data/docs/MessagesApi.md +3 -3
- data/docs/WebhookPayloadMessageMessageAttachmentsInner.md +4 -2
- data/docs/WebhookPayloadMessageSentMessageAttachmentsInner.md +4 -2
- data/docs/WebhookPayloadMessageSentMessageSender.md +4 -4
- data/lib/zernio-sdk/api/connect_api.rb +8 -8
- data/lib/zernio-sdk/api/messages_api.rb +4 -4
- data/lib/zernio-sdk/models/get_inbox_conversation_messages200_response_messages_inner_attachments_inner.rb +11 -1
- data/lib/zernio-sdk/models/webhook_payload_message_message_attachments_inner.rb +13 -3
- data/lib/zernio-sdk/models/webhook_payload_message_sent_message_attachments_inner.rb +13 -3
- data/lib/zernio-sdk/models/webhook_payload_message_sent_message_sender.rb +5 -0
- data/lib/zernio-sdk/version.rb +1 -1
- data/openapi.yaml +147 -9
- data/spec/api/connect_api_spec.rb +4 -4
- data/spec/api/messages_api_spec.rb +2 -2
- data/spec/models/get_inbox_conversation_messages200_response_messages_inner_attachments_inner_spec.rb +6 -0
- data/spec/models/webhook_payload_message_message_attachments_inner_spec.rb +6 -0
- data/spec/models/webhook_payload_message_sent_message_attachments_inner_spec.rb +6 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 99efc3c0a5149d104aacd53a7e08b4683eb5ea5c39d34e60baaf34078d383b04
|
|
4
|
+
data.tar.gz: fc4b1aa17db17d9fa4e3eff504e7f4e2efdc6bf97af1207537c1244b98dd0563
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fa12d26b387723babbc25c446e17b70a8c0cad6640e21266af7c48125fc3844b79b2e1c9a597826c82e69230ccb2f26657883d18c4711ebbbe73bee7fe573159
|
|
7
|
+
data.tar.gz: 2b3244ad925082cf470bd406367484e248a5a32323ef5cb8ff4a9441984e163a3b5b322c216e067cef2b6fd0f339c36eaa56949b02dc5e15bc120e03d0c2b1b8
|
data/docs/ConnectApi.md
CHANGED
|
@@ -343,7 +343,7 @@ end
|
|
|
343
343
|
|
|
344
344
|
Connect ads for a platform
|
|
345
345
|
|
|
346
|
-
Unified ads connection endpoint. Creates a dedicated ads SocialAccount for the specified platform. Same-token platforms (facebook, instagram, linkedin, pinterest):
|
|
346
|
+
Unified ads connection endpoint. Creates a dedicated ads SocialAccount for the specified platform. Same-token platforms (facebook, instagram, linkedin, pinterest): the ads SocialAccount (metaads, linkedinads, pinterestads) reuses the OAuth token of the parent posting account, but only when an active parent exists and, for facebook and instagram, its stored token carries ads_management and ads_read (linkedin and pinterest need no extra scope). In that case no extra OAuth happens and the response is alreadyConnected: true. When no such parent exists, or the scopes are missing, the endpoint returns an authUrl and a full OAuth round trip is required. When a parent exists but carries no token usable for ad accounts, the call fails with 400 RECONNECT_REQUIRED. Independently of the branch, the call can return 403 ADS_ADDON_REQUIRED without the ads add-on and 402 PAYMENT_REQUIRED when the billing gate is closed. Meta Ads prerequisite: connecting Meta Ads (via facebook or instagram) requires a Facebook Page. Not because the ad account is read through a Page, but because both parent posting accounts are: the facebook flow only offers Pages you manage, and the instagram flow with loginMethod=facebook_login only offers Instagram accounts linked to one of those Pages. Without a Page there is no parent account to inherit a token from. A user who manages no Facebook Page cannot complete this connection, and the facebook flow ends with error=no_facebook_pages. Separate-token platforms (tiktok, twitter): Starts the platform-specific marketing API OAuth flow and creates an ads SocialAccount (tiktokads, xads) with its own token. If the ads account already exists, returns alreadyConnected: true. - tiktok: accountId is OPTIONAL. With accountId, the new tiktokads account links to that posting account (parentAccountId set) — Spark Ads + standalone ads using the posting TT_USER identity become available. Without accountId, ads-only mode kicks in: the new tiktokads account has parentAccountId=null and standalone ads use a synthetic CUSTOMIZED_USER (\"Brand Identity\"); Spark Ads are unavailable because TikTok requires a posting account for them. The Brand Identity is configured separately via PATCH /v1/connect/tiktok-ads (or inline on POST /v1/ads/create via the brandIdentity field). - twitter (X Ads): accountId is REQUIRED. There's no ads-only mode — tweets need to be authored by a real X user. Standalone platforms (googleads): Starts the Google Ads OAuth flow and creates a standalone ads SocialAccount (googleads) with no parent. If the account already exists, returns alreadyConnected: true. Ads accounts appear as regular SocialAccount documents with ads platform values (e.g., metaads, tiktokads) in GET /v1/accounts.
|
|
347
347
|
|
|
348
348
|
### Examples
|
|
349
349
|
|
|
@@ -357,11 +357,11 @@ Zernio.configure do |config|
|
|
|
357
357
|
end
|
|
358
358
|
|
|
359
359
|
api_instance = Zernio::ConnectApi.new
|
|
360
|
-
platform = 'facebook' # String | Platform to connect ads for. Only platforms with ads support are accepted.
|
|
360
|
+
platform = 'facebook' # String | Platform to connect ads for. Only platforms with ads support are accepted. `instagram` requires an Instagram account connected with loginMethod=facebook_login whose token carries ads_management and ads_read. With an account connected through the default instagram_login flow no ads account can be created; do not use this value for those accounts.
|
|
361
361
|
profile_id = 'profile_id_example' # String | Your Zernio profile ID
|
|
362
362
|
opts = {
|
|
363
363
|
account_id: 'account_id_example', # String | Existing SocialAccount ID. Required for `twitter` (X Ads). Optional for `tiktok` — omit to enter ads-only mode (no TikTok posting account linked; ad creation uses a Brand Identity instead of a TT_USER). Ignored for same-token (`facebook`, `instagram`, `linkedin`, `pinterest`) and standalone (`googleads`) platforms.
|
|
364
|
-
redirect_url: 'redirect_url_example', # String | Custom URL the browser is sent to once the OAuth flow finishes. Honored on every ads platform, including the separate-token (`tiktok`, `twitter`) and standalone (`googleads`) flows. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. On success `tiktok`, `twitter` and `googleads` land on the URL unchanged, while the same-token platforms (`facebook`, `instagram`, `linkedin`, `pinterest`) append `connected`, `profileId`, `accountId`, `username` and, on API-key calls, `connect_token`. On failure
|
|
364
|
+
redirect_url: 'redirect_url_example', # String | Custom URL the browser is sent to once the OAuth flow finishes. Honored on every ads platform, including the separate-token (`tiktok`, `twitter`) and standalone (`googleads`) flows. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. On success `tiktok`, `twitter` and `googleads` land on the URL unchanged, while the same-token platforms (`facebook`, `instagram`, `linkedin`, `pinterest`) append `connected`, `profileId`, `accountId`, `username` and, on API-key calls, `connect_token`. On failure the same error contract applies as on GET /v1/connect/{platform}: `error` and `platform` are always appended, other params are optional, and the value list there is not exhaustive. Note that on the tiktok, twitter and googleads flows `platform` carries the ads platform id (`tiktokads`, `xads`, `googleads`), not the value used in the request path. When omitted, the browser lands on the Zernio dashboard.
|
|
365
365
|
headless: true, # Boolean | Enable headless mode (same-token platforms only)
|
|
366
366
|
force: true, # Boolean | Force a fresh OAuth even when an account already exists. Normally the endpoint returns `alreadyConnected: true` whenever a connected account is found, keying off its active state rather than token liveness. Set `force=true` to bypass that and always receivean `authUrl`. Completing the returned OAuth refreshes the stored token on the existing posting and ads accounts in place.
|
|
367
367
|
ad_account_id: 'act_1330190928038136', # String | Scope ad sync to a single platform ad account. Without this param, sync covers every ad account the connected token can see. Supported on `facebook`/`instagram` (Meta, `act_<digits>`), `linkedin` (bare numeric sponsored-account id), `googleads` (bare customer id digits) and `twitter` (X Ads, base36 account id). `tiktok` scopes advertisers at OAuth and `pinterest` has no ads discovery, so both ignore it. Meta ids are additionally validated against the connected token; unreachable IDs return 400. Setting a scope also removes already synced ads from de-scoped ad accounts. For multiple accounts use `adAccountIds` instead.
|
|
@@ -399,10 +399,10 @@ end
|
|
|
399
399
|
|
|
400
400
|
| Name | Type | Description | Notes |
|
|
401
401
|
| ---- | ---- | ----------- | ----- |
|
|
402
|
-
| **platform** | **String** | Platform to connect ads for. Only platforms with ads support are accepted. | |
|
|
402
|
+
| **platform** | **String** | Platform to connect ads for. Only platforms with ads support are accepted. `instagram` requires an Instagram account connected with loginMethod=facebook_login whose token carries ads_management and ads_read. With an account connected through the default instagram_login flow no ads account can be created; do not use this value for those accounts. | |
|
|
403
403
|
| **profile_id** | **String** | Your Zernio profile ID | |
|
|
404
404
|
| **account_id** | **String** | Existing SocialAccount ID. Required for `twitter` (X Ads). Optional for `tiktok` — omit to enter ads-only mode (no TikTok posting account linked; ad creation uses a Brand Identity instead of a TT_USER). Ignored for same-token (`facebook`, `instagram`, `linkedin`, `pinterest`) and standalone (`googleads`) platforms. | [optional] |
|
|
405
|
-
| **redirect_url** | **String** | Custom URL the browser is sent to once the OAuth flow finishes. Honored on every ads platform, including the separate-token (`tiktok`, `twitter`) and standalone (`googleads`) flows. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. On success `tiktok`, `twitter` and `googleads` land on the URL unchanged, while the same-token platforms (`facebook`, `instagram`, `linkedin`, `pinterest`) append `connected`, `profileId`, `accountId`, `username` and, on API-key calls, `connect_token`. On failure
|
|
405
|
+
| **redirect_url** | **String** | Custom URL the browser is sent to once the OAuth flow finishes. Honored on every ads platform, including the separate-token (`tiktok`, `twitter`) and standalone (`googleads`) flows. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. On success `tiktok`, `twitter` and `googleads` land on the URL unchanged, while the same-token platforms (`facebook`, `instagram`, `linkedin`, `pinterest`) append `connected`, `profileId`, `accountId`, `username` and, on API-key calls, `connect_token`. On failure the same error contract applies as on GET /v1/connect/{platform}: `error` and `platform` are always appended, other params are optional, and the value list there is not exhaustive. Note that on the tiktok, twitter and googleads flows `platform` carries the ads platform id (`tiktokads`, `xads`, `googleads`), not the value used in the request path. When omitted, the browser lands on the Zernio dashboard. | [optional] |
|
|
406
406
|
| **headless** | **Boolean** | Enable headless mode (same-token platforms only) | [optional][default to false] |
|
|
407
407
|
| **force** | **Boolean** | Force a fresh OAuth even when an account already exists. Normally the endpoint returns `alreadyConnected: true` whenever a connected account is found, keying off its active state rather than token liveness. Set `force=true` to bypass that and always receivean `authUrl`. Completing the returned OAuth refreshes the stored token on the existing posting and ads accounts in place. | [optional][default to false] |
|
|
408
408
|
| **ad_account_id** | **String** | Scope ad sync to a single platform ad account. Without this param, sync covers every ad account the connected token can see. Supported on `facebook`/`instagram` (Meta, `act_<digits>`), `linkedin` (bare numeric sponsored-account id), `googleads` (bare customer id digits) and `twitter` (X Ads, base36 account id). `tiktok` scopes advertisers at OAuth and `pinterest` has no ads discovery, so both ignore it. Meta ids are additionally validated against the connected token; unreachable IDs return 400. Setting a scope also removes already synced ads from de-scoped ad accounts. For multiple accounts use `adAccountIds` instead. | [optional] |
|
|
@@ -996,7 +996,7 @@ api_instance = Zernio::ConnectApi.new
|
|
|
996
996
|
platform = 'facebook' # String | Social media platform to connect
|
|
997
997
|
profile_id = 'profile_id_example' # String | Your Zernio profile ID (get from /v1/profiles). For WhatsApp, a Zernio-provisioned number can only be connected on the profile it was provisioned to; connecting from any other profile is rejected with a 409.
|
|
998
998
|
opts = {
|
|
999
|
-
redirect_url: 'redirect_url_example', # String | Your custom redirect URL after connection completes. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. Result params are appended with the URL API, so an existing query string is preserved. Standard mode appends connected={platform}&profileId=X&accountId=Y&username=Z. Headless mode appends OAuth data params for platforms requiring selection (e.g. LinkedIn orgs, Facebook pages). If no selection is needed, the account is created directly and the redirect includes accountId.
|
|
999
|
+
redirect_url: 'redirect_url_example', # String | Your custom redirect URL after connection completes. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. Result params are appended with the URL API, so an existing query string is preserved. Standard mode appends connected={platform}&profileId=X&accountId=Y&username=Z. Headless mode appends OAuth data params for platforms requiring selection (e.g. LinkedIn orgs, Facebook pages). If no selection is needed, the account is created directly and the redirect includes accountId. On failure, the browser is sent to the same redirect_url with `error` and `platform` appended. `error` and `platform` are always present. `error_message`, `is_user_fixable`, `reason` and `dashboard_url` are conditional and must be treated as optional. This list is NOT exhaustive and new values may be added at any time. Treat an unrecognized value as a generic failure rather than matching it exhaustively. Existing values are not renamed or removed without notice. OAuth and callback: oauth_denied, invalid_callback, invalid_state, unsupported_platform, connection_failed, internal_error, token_exchange_failed, byok_config_error, personal_account_not_supported, missing_google_permissions, platform_requires_destination, reconnect_account_mismatch, invalid_request Access and limits: profile_not_found, invalid_profile_id, access_denied, account_limit_exceeded, profile_limit_exceeded, payment_required Destination selection: no_facebook_pages, facebook_pages_error, no_google_locations, google_locations_error, google_permission_denied, no_snapchat_public_profiles, snapchat_profiles_error, discord_no_guild, slack_no_team WhatsApp: whatsapp_error, one_whatsapp_per_profile, whatsapp_number_already_connected, whatsapp_number_pinned_to_profile, connection_cancelled Google Ads (platform=googleads): google_ads_auth_failed, google_ads_invalid_state, google_ads_config_error, google_ads_token_failed, google_ads_quota_exhausted, google_ads_callback_error TikTok Ads (platform=tiktokads): tiktok_ads_auth_failed, tiktok_ads_invalid_state, tiktok_ads_access_denied, tiktok_ads_config_error, tiktok_ads_token_failed, tiktok_ads_account_not_found, tiktok_ads_callback_error X Ads (platform=xads): x_ads_denied, x_ads_auth_failed, x_ads_config_error, x_ads_account_not_found, x_ads_state_error, x_ads_token_failed, x_ads_token_missing, x_ads_callback_error Shopify (platform=shopify): shopify_auth_failed, shopify_config_error, shopify_invalid_state, shopify_invalid_hmac, shopify_invalid_shop, shopify_missing_scopes, shopify_callback_error 1. On this endpoint every upstream OAuth error is collapsed into `oauth_denied`. The provider's own value (for example Meta's `access_denied`) is not forwarded. The dedicated ads flows below are different: they use their own denial slugs and `google_ads_auth_failed` and `tiktok_ads_auth_failed` may carry the provider's raw error string in `error_message`. 2. On the tiktok and twitter ads flows `platform` carries the ads platform id (`tiktokads`, `xads`), not the value used in the request path. The googleads and shopify flows report `googleads` and `shopify`.
|
|
1000
1000
|
headless: true, # Boolean | When true, the user is redirected to your redirect_url with raw OAuth data (code, state) instead of Zernio's default account selection UI. Use this to build a custom connect experience.
|
|
1001
1001
|
login_method: 'instagram_login', # String | Instagram only. Which of the two Instagram connection methods to use. Ignored for every other platform. `instagram_login` (the default, and what you get if you omit this): the Instagram Login dialog. The user authorizes their Instagram professional account directly, no Facebook Page required. `facebook_login`: the Facebook Login dialog, i.e. \"Instagram API with Facebook Login\". The user authorizes a Facebook Page that has a linked Instagram professional account, and every API call for that account then runs through the Page. Use this when the customer manages Instagram through a Page and expects the Facebook consent screen. Because the user has to pick which Page to connect, the callback continues at the account-selection step, `/v1/connect/instagram/select-account`. `facebook_login` supports `headless=true` like the other selection platforms: the callback redirects to your `redirect_url` with `profileId`, `tempToken`, `platform=instagram`, `step=select_account` and `connect_token`, which you pass into the select-account endpoints to finish. The default `instagram_login` has no selection step, so it connects the account directly.
|
|
1002
1002
|
onboarding: 'api' # String | WhatsApp only. Ignored for every other platform. Controls which screen Meta's Embedded Signup popup shows. If omitted, the connection defaults to coexistence (same as `business_app` below), preserving existing behavior for numbers already on the WhatsApp Business app. `api`: standard Embedded Signup, showing Meta's WABA/number picker. Use this to connect a phone number already on Cloud API elsewhere. `business_app`: coexistence, i.e. 'Connect existing WhatsApp Business app' (a number shared between Cloud API and the consumer WhatsApp Business app).
|
|
@@ -1035,7 +1035,7 @@ end
|
|
|
1035
1035
|
| ---- | ---- | ----------- | ----- |
|
|
1036
1036
|
| **platform** | **String** | Social media platform to connect | |
|
|
1037
1037
|
| **profile_id** | **String** | Your Zernio profile ID (get from /v1/profiles). For WhatsApp, a Zernio-provisioned number can only be connected on the profile it was provisioned to; connecting from any other profile is rejected with a 409. | |
|
|
1038
|
-
| **redirect_url** | **String** | Your custom redirect URL after connection completes. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. Result params are appended with the URL API, so an existing query string is preserved. Standard mode appends connected={platform}&profileId=X&accountId=Y&username=Z. Headless mode appends OAuth data params for platforms requiring selection (e.g. LinkedIn orgs, Facebook pages). If no selection is needed, the account is created directly and the redirect includes accountId. | [optional] |
|
|
1038
|
+
| **redirect_url** | **String** | Your custom redirect URL after connection completes. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. Result params are appended with the URL API, so an existing query string is preserved. Standard mode appends connected={platform}&profileId=X&accountId=Y&username=Z. Headless mode appends OAuth data params for platforms requiring selection (e.g. LinkedIn orgs, Facebook pages). If no selection is needed, the account is created directly and the redirect includes accountId. On failure, the browser is sent to the same redirect_url with `error` and `platform` appended. `error` and `platform` are always present. `error_message`, `is_user_fixable`, `reason` and `dashboard_url` are conditional and must be treated as optional. This list is NOT exhaustive and new values may be added at any time. Treat an unrecognized value as a generic failure rather than matching it exhaustively. Existing values are not renamed or removed without notice. OAuth and callback: oauth_denied, invalid_callback, invalid_state, unsupported_platform, connection_failed, internal_error, token_exchange_failed, byok_config_error, personal_account_not_supported, missing_google_permissions, platform_requires_destination, reconnect_account_mismatch, invalid_request Access and limits: profile_not_found, invalid_profile_id, access_denied, account_limit_exceeded, profile_limit_exceeded, payment_required Destination selection: no_facebook_pages, facebook_pages_error, no_google_locations, google_locations_error, google_permission_denied, no_snapchat_public_profiles, snapchat_profiles_error, discord_no_guild, slack_no_team WhatsApp: whatsapp_error, one_whatsapp_per_profile, whatsapp_number_already_connected, whatsapp_number_pinned_to_profile, connection_cancelled Google Ads (platform=googleads): google_ads_auth_failed, google_ads_invalid_state, google_ads_config_error, google_ads_token_failed, google_ads_quota_exhausted, google_ads_callback_error TikTok Ads (platform=tiktokads): tiktok_ads_auth_failed, tiktok_ads_invalid_state, tiktok_ads_access_denied, tiktok_ads_config_error, tiktok_ads_token_failed, tiktok_ads_account_not_found, tiktok_ads_callback_error X Ads (platform=xads): x_ads_denied, x_ads_auth_failed, x_ads_config_error, x_ads_account_not_found, x_ads_state_error, x_ads_token_failed, x_ads_token_missing, x_ads_callback_error Shopify (platform=shopify): shopify_auth_failed, shopify_config_error, shopify_invalid_state, shopify_invalid_hmac, shopify_invalid_shop, shopify_missing_scopes, shopify_callback_error 1. On this endpoint every upstream OAuth error is collapsed into `oauth_denied`. The provider's own value (for example Meta's `access_denied`) is not forwarded. The dedicated ads flows below are different: they use their own denial slugs and `google_ads_auth_failed` and `tiktok_ads_auth_failed` may carry the provider's raw error string in `error_message`. 2. On the tiktok and twitter ads flows `platform` carries the ads platform id (`tiktokads`, `xads`), not the value used in the request path. The googleads and shopify flows report `googleads` and `shopify`. | [optional] |
|
|
1039
1039
|
| **headless** | **Boolean** | When true, the user is redirected to your redirect_url with raw OAuth data (code, state) instead of Zernio's default account selection UI. Use this to build a custom connect experience. | [optional][default to false] |
|
|
1040
1040
|
| **login_method** | **String** | Instagram only. Which of the two Instagram connection methods to use. Ignored for every other platform. `instagram_login` (the default, and what you get if you omit this): the Instagram Login dialog. The user authorizes their Instagram professional account directly, no Facebook Page required. `facebook_login`: the Facebook Login dialog, i.e. \"Instagram API with Facebook Login\". The user authorizes a Facebook Page that has a linked Instagram professional account, and every API call for that account then runs through the Page. Use this when the customer manages Instagram through a Page and expects the Facebook consent screen. Because the user has to pick which Page to connect, the callback continues at the account-selection step, `/v1/connect/instagram/select-account`. `facebook_login` supports `headless=true` like the other selection platforms: the callback redirects to your `redirect_url` with `profileId`, `tempToken`, `platform=instagram`, `step=select_account` and `connect_token`, which you pass into the select-account endpoints to finish. The default `instagram_login` has no selection step, so it connects the account directly. | [optional][default to 'instagram_login'] |
|
|
1041
1041
|
| **onboarding** | **String** | WhatsApp only. Ignored for every other platform. Controls which screen Meta's Embedded Signup popup shows. If omitted, the connection defaults to coexistence (same as `business_app` below), preserving existing behavior for numbers already on the WhatsApp Business app. `api`: standard Embedded Signup, showing Meta's WABA/number picker. Use this to connect a phone number already on Cloud API elsewhere. `business_app`: coexistence, i.e. 'Connect existing WhatsApp Business app' (a number shared between Cloud API and the consumer WhatsApp Business app). | [optional] |
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
| ---- | ---- | ----------- | ----- |
|
|
7
7
|
| **id** | **String** | | [optional] |
|
|
8
8
|
| **type** | **String** | | [optional] |
|
|
9
|
+
| **original_type** | **String** | Instagram and Facebook only, and present only when it differs from `type`. Meta's own type before normalization: `ig_reel` and `reel` become `video`, while `ig_post`, `post`, `ig_story` and `story_mention` become `share`. A story mention is `type: \"share\"` with `originalType: \"story_mention\"`; render on this field, since `share` alone is ambiguous. | [optional] |
|
|
9
10
|
| **url** | **String** | Direct media link. On Instagram and Facebook this is a signed Meta CDN url that EXPIRES: use it now, do not store it. Persist `refreshUrl` instead. | [optional] |
|
|
10
11
|
| **refresh_url** | **String** | Instagram and Facebook only. Endpoint that resolves this attachment to a working url every time, re-minting it from Meta when the stored one has expired. Safe to store and render indefinitely. | [optional] |
|
|
11
12
|
| **filename** | **String** | | [optional] |
|
|
@@ -19,6 +20,7 @@ require 'zernio-sdk'
|
|
|
19
20
|
instance = Zernio::GetInboxConversationMessages200ResponseMessagesInnerAttachmentsInner.new(
|
|
20
21
|
id: null,
|
|
21
22
|
type: null,
|
|
23
|
+
original_type: null,
|
|
22
24
|
url: null,
|
|
23
25
|
refresh_url: null,
|
|
24
26
|
filename: null,
|
data/docs/MessagesApi.md
CHANGED
|
@@ -465,7 +465,7 @@ end
|
|
|
465
465
|
|
|
466
466
|
Resolve message attachment
|
|
467
467
|
|
|
468
|
-
Resolve one attachment on a message to a media url that works right now. Instagram and Facebook sign DM media urls per request and expire them, so the `url` on a message is a snapshot: it works when you read the message and stops working later. This endpoint checks the stored url and, when it has gone stale, re-mints the message's media from Meta and persists it before answering. The message id never expires, so this URL is the one to store
|
|
468
|
+
Resolve one attachment on a message to a media url that works right now. Instagram and Facebook sign DM media urls per request and expire them, so the `url` on a message is a snapshot: it works when you read the message and stops working later. This endpoint checks the stored url and, when it has gone stale, re-mints the message's media from Meta and persists it before answering. The message id never expires, so this URL is the one to store. It is returned ready-made on each attachment as `refreshUrl` when you read a message over REST. **Webhook payloads do not carry `refreshUrl`**, so a webhook-driven integration builds this URL itself. Every piece is in the event: `message.conversationId`, `message.platformMessageId`, the attachment's zero-based position, and `account.accountId`. Note that **`accountId` is a required query parameter**; omitting it returns `400` `missing_required_field`, which is the same requirement `GET /v1/whatsapp/media/{mediaId}` has. By default it responds `302` to the live media url, so it can be used directly as an `<img src>` on a browser session. API-key integrators should pass `?format=json` and read `url` off the body, since a browser cannot attach an Authorization header to an image request. Only Instagram and Facebook media can be re-minted. On other platforms the stored url is returned as-is when it still resolves, and `404` otherwise.
|
|
469
469
|
|
|
470
470
|
### Examples
|
|
471
471
|
|
|
@@ -482,7 +482,7 @@ api_instance = Zernio::MessagesApi.new
|
|
|
482
482
|
conversation_id = 'conversation_id_example' # String | The conversation ID (Zernio id or platform conversation id)
|
|
483
483
|
message_id = 'message_id_example' # String | The message id as returned by the list-messages endpoint (the platform message id)
|
|
484
484
|
index = 56 # Integer | Zero-based position of the attachment in the message's attachments array
|
|
485
|
-
account_id = 'account_id_example' # String | Social account ID
|
|
485
|
+
account_id = 'account_id_example' # String | Social account ID. Required: without it the request returns 400 missing_required_field.
|
|
486
486
|
opts = {
|
|
487
487
|
format: 'redirect' # String | `redirect` (default) answers 302 to the media; `json` returns the url in the body
|
|
488
488
|
}
|
|
@@ -521,7 +521,7 @@ end
|
|
|
521
521
|
| **conversation_id** | **String** | The conversation ID (Zernio id or platform conversation id) | |
|
|
522
522
|
| **message_id** | **String** | The message id as returned by the list-messages endpoint (the platform message id) | |
|
|
523
523
|
| **index** | **Integer** | Zero-based position of the attachment in the message's attachments array | |
|
|
524
|
-
| **account_id** | **String** | Social account ID | |
|
|
524
|
+
| **account_id** | **String** | Social account ID. Required: without it the request returns 400 missing_required_field. | |
|
|
525
525
|
| **format** | **String** | `redirect` (default) answers 302 to the media; `json` returns the url in the body | [optional][default to 'redirect'] |
|
|
526
526
|
|
|
527
527
|
### Return type
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
| Name | Type | Description | Notes |
|
|
6
6
|
| ---- | ---- | ----------- | ----- |
|
|
7
|
-
| **type** | **String** | Attachment type (image, video, file, sticker, audio) | |
|
|
8
|
-
| **
|
|
7
|
+
| **type** | **String** | Attachment type (image, video, file, sticker, audio, share) | |
|
|
8
|
+
| **original_type** | **String** | Instagram and Facebook only, and present only when it differs from `type`. Meta's own attachment type before Zernio normalized it: `ig_reel` and `reel` become `video`, while `ig_post`, `post`, `ig_story` and `story_mention` all become `share`. Read it before rendering, because `type: \"share\"` alone is ambiguous. In particular a story mention arrives as `type: \"share\"` with `originalType: \"story_mention\"`; treating an unrecognized type as a generic document shows your agent \"document received\" for what is usually a lead. | [optional] |
|
|
9
|
+
| **url** | **String** | Where to fetch the attachment. **The contract differs by platform.** - **WhatsApp**: points at `GET /v1/whatsapp/media/{mediaId}`, an authenticated Zernio endpoint. You MUST send `Authorization: Bearer <your API key>`; fetching it without that header returns `401`. Download and store the bytes when this webhook arrives: Meta drops inbound media after a limited retention window, after which the endpoint answers `400` permanently and the media is unrecoverable. - **Instagram / Facebook / Telegram**: a direct platform CDN link that needs no authentication and expires on the platform's own schedule. **Webhook attachments carry no `refreshUrl`.** That field is stamped only when you read a message back over REST (`GET /v1/inbox/conversations/{conversationId}/messages`). On Instagram and Facebook the url above is a signed Meta CDN link that expires, so do not persist it: store the message id and resolve the media through `GET /v1/inbox/conversations/{conversationId}/messages/{messageId}/attachments/{index}?accountId={accountId}`, which re-mints it on demand. Every value that URL needs is already in this payload: `message.conversationId`, `message.platformMessageId`, `account.accountId`, and the attachment's zero-based position in this array. | |
|
|
9
10
|
| **payload** | **Object** | Additional attachment metadata | [optional] |
|
|
10
11
|
|
|
11
12
|
## Example
|
|
@@ -15,6 +16,7 @@ require 'zernio-sdk'
|
|
|
15
16
|
|
|
16
17
|
instance = Zernio::WebhookPayloadMessageMessageAttachmentsInner.new(
|
|
17
18
|
type: null,
|
|
19
|
+
original_type: null,
|
|
18
20
|
url: null,
|
|
19
21
|
payload: null
|
|
20
22
|
)
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
| Name | Type | Description | Notes |
|
|
6
6
|
| ---- | ---- | ----------- | ----- |
|
|
7
|
-
| **type** | **String** | Attachment type (image, video, file, sticker, audio) | |
|
|
8
|
-
| **
|
|
7
|
+
| **type** | **String** | Attachment type (image, video, file, sticker, audio, share) | |
|
|
8
|
+
| **original_type** | **String** | Instagram and Facebook only, and present only when it differs from `type`. Meta's own attachment type before Zernio normalized it. See the same field on message.received for the full mapping. | [optional] |
|
|
9
|
+
| **url** | **String** | Where to fetch the attachment. For outgoing messages this is the media URL as sent, so for WhatsApp it is the URL you supplied when publishing (WhatsApp sends media by link), not a Zernio endpoint, and it needs no Zernio credentials. Contrast the inbound direction: `message.received` attachment URLs on WhatsApp point at the authenticated `GET /v1/whatsapp/media/{mediaId}`. As on `message.received`, webhook attachments carry no `refreshUrl`: that field is stamped only on the REST read. Resolve Instagram and Facebook media through `GET /v1/inbox/conversations/{conversationId}/messages/{messageId}/attachments/{index}?accountId={accountId}`. | |
|
|
9
10
|
| **payload** | **Object** | Additional attachment metadata | [optional] |
|
|
10
11
|
|
|
11
12
|
## Example
|
|
@@ -15,6 +16,7 @@ require 'zernio-sdk'
|
|
|
15
16
|
|
|
16
17
|
instance = Zernio::WebhookPayloadMessageSentMessageAttachmentsInner.new(
|
|
17
18
|
type: null,
|
|
19
|
+
original_type: null,
|
|
18
20
|
url: null,
|
|
19
21
|
payload: null
|
|
20
22
|
)
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
| Name | Type | Description | Notes |
|
|
6
6
|
| ---- | ---- | ----------- | ----- |
|
|
7
|
-
| **id** | **String** |
|
|
7
|
+
| **id** | **String** | The Zernio account id of the connected account that sent the message, not a contact id. | |
|
|
8
8
|
| **contact_id** | **String** | Always omitted on this event: the sender is the business, not a contact. Use conversation.contactId to join back to the CRM Contact. | [optional] |
|
|
9
|
-
| **name** | **String** |
|
|
10
|
-
| **username** | **String** |
|
|
11
|
-
| **picture** | **String** |
|
|
9
|
+
| **name** | **String** | Display name of your connected account. | [optional] |
|
|
10
|
+
| **username** | **String** | Username of your connected account. | [optional] |
|
|
11
|
+
| **picture** | **String** | Profile picture of your connected account. | [optional] |
|
|
12
12
|
|
|
13
13
|
## Example
|
|
14
14
|
|
|
@@ -297,12 +297,12 @@ module Zernio
|
|
|
297
297
|
end
|
|
298
298
|
|
|
299
299
|
# Connect ads for a platform
|
|
300
|
-
# Unified ads connection endpoint. Creates a dedicated ads SocialAccount for the specified platform. Same-token platforms (facebook, instagram, linkedin, pinterest):
|
|
301
|
-
# @param platform [String] Platform to connect ads for. Only platforms with ads support are accepted.
|
|
300
|
+
# Unified ads connection endpoint. Creates a dedicated ads SocialAccount for the specified platform. Same-token platforms (facebook, instagram, linkedin, pinterest): the ads SocialAccount (metaads, linkedinads, pinterestads) reuses the OAuth token of the parent posting account, but only when an active parent exists and, for facebook and instagram, its stored token carries ads_management and ads_read (linkedin and pinterest need no extra scope). In that case no extra OAuth happens and the response is alreadyConnected: true. When no such parent exists, or the scopes are missing, the endpoint returns an authUrl and a full OAuth round trip is required. When a parent exists but carries no token usable for ad accounts, the call fails with 400 RECONNECT_REQUIRED. Independently of the branch, the call can return 403 ADS_ADDON_REQUIRED without the ads add-on and 402 PAYMENT_REQUIRED when the billing gate is closed. Meta Ads prerequisite: connecting Meta Ads (via facebook or instagram) requires a Facebook Page. Not because the ad account is read through a Page, but because both parent posting accounts are: the facebook flow only offers Pages you manage, and the instagram flow with loginMethod=facebook_login only offers Instagram accounts linked to one of those Pages. Without a Page there is no parent account to inherit a token from. A user who manages no Facebook Page cannot complete this connection, and the facebook flow ends with error=no_facebook_pages. Separate-token platforms (tiktok, twitter): Starts the platform-specific marketing API OAuth flow and creates an ads SocialAccount (tiktokads, xads) with its own token. If the ads account already exists, returns alreadyConnected: true. - tiktok: accountId is OPTIONAL. With accountId, the new tiktokads account links to that posting account (parentAccountId set) — Spark Ads + standalone ads using the posting TT_USER identity become available. Without accountId, ads-only mode kicks in: the new tiktokads account has parentAccountId=null and standalone ads use a synthetic CUSTOMIZED_USER (\"Brand Identity\"); Spark Ads are unavailable because TikTok requires a posting account for them. The Brand Identity is configured separately via PATCH /v1/connect/tiktok-ads (or inline on POST /v1/ads/create via the brandIdentity field). - twitter (X Ads): accountId is REQUIRED. There's no ads-only mode — tweets need to be authored by a real X user. Standalone platforms (googleads): Starts the Google Ads OAuth flow and creates a standalone ads SocialAccount (googleads) with no parent. If the account already exists, returns alreadyConnected: true. Ads accounts appear as regular SocialAccount documents with ads platform values (e.g., metaads, tiktokads) in GET /v1/accounts.
|
|
301
|
+
# @param platform [String] Platform to connect ads for. Only platforms with ads support are accepted. `instagram` requires an Instagram account connected with loginMethod=facebook_login whose token carries ads_management and ads_read. With an account connected through the default instagram_login flow no ads account can be created; do not use this value for those accounts.
|
|
302
302
|
# @param profile_id [String] Your Zernio profile ID
|
|
303
303
|
# @param [Hash] opts the optional parameters
|
|
304
304
|
# @option opts [String] :account_id Existing SocialAccount ID. Required for `twitter` (X Ads). Optional for `tiktok` — omit to enter ads-only mode (no TikTok posting account linked; ad creation uses a Brand Identity instead of a TT_USER). Ignored for same-token (`facebook`, `instagram`, `linkedin`, `pinterest`) and standalone (`googleads`) platforms.
|
|
305
|
-
# @option opts [String] :redirect_url Custom URL the browser is sent to once the OAuth flow finishes. Honored on every ads platform, including the separate-token (`tiktok`, `twitter`) and standalone (`googleads`) flows. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. On success `tiktok`, `twitter` and `googleads` land on the URL unchanged, while the same-token platforms (`facebook`, `instagram`, `linkedin`, `pinterest`) append `connected`, `profileId`, `accountId`, `username` and, on API-key calls, `connect_token`. On failure
|
|
305
|
+
# @option opts [String] :redirect_url Custom URL the browser is sent to once the OAuth flow finishes. Honored on every ads platform, including the separate-token (`tiktok`, `twitter`) and standalone (`googleads`) flows. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. On success `tiktok`, `twitter` and `googleads` land on the URL unchanged, while the same-token platforms (`facebook`, `instagram`, `linkedin`, `pinterest`) append `connected`, `profileId`, `accountId`, `username` and, on API-key calls, `connect_token`. On failure the same error contract applies as on GET /v1/connect/{platform}: `error` and `platform` are always appended, other params are optional, and the value list there is not exhaustive. Note that on the tiktok, twitter and googleads flows `platform` carries the ads platform id (`tiktokads`, `xads`, `googleads`), not the value used in the request path. When omitted, the browser lands on the Zernio dashboard.
|
|
306
306
|
# @option opts [Boolean] :headless Enable headless mode (same-token platforms only) (default to false)
|
|
307
307
|
# @option opts [Boolean] :force Force a fresh OAuth even when an account already exists. Normally the endpoint returns `alreadyConnected: true` whenever a connected account is found, keying off its active state rather than token liveness. Set `force=true` to bypass that and always receivean `authUrl`. Completing the returned OAuth refreshes the stored token on the existing posting and ads accounts in place. (default to false)
|
|
308
308
|
# @option opts [String] :ad_account_id Scope ad sync to a single platform ad account. Without this param, sync covers every ad account the connected token can see. Supported on `facebook`/`instagram` (Meta, `act_<digits>`), `linkedin` (bare numeric sponsored-account id), `googleads` (bare customer id digits) and `twitter` (X Ads, base36 account id). `tiktok` scopes advertisers at OAuth and `pinterest` has no ads discovery, so both ignore it. Meta ids are additionally validated against the connected token; unreachable IDs return 400. Setting a scope also removes already synced ads from de-scoped ad accounts. For multiple accounts use `adAccountIds` instead.
|
|
@@ -314,12 +314,12 @@ module Zernio
|
|
|
314
314
|
end
|
|
315
315
|
|
|
316
316
|
# Connect ads for a platform
|
|
317
|
-
# Unified ads connection endpoint. Creates a dedicated ads SocialAccount for the specified platform. Same-token platforms (facebook, instagram, linkedin, pinterest):
|
|
318
|
-
# @param platform [String] Platform to connect ads for. Only platforms with ads support are accepted.
|
|
317
|
+
# Unified ads connection endpoint. Creates a dedicated ads SocialAccount for the specified platform. Same-token platforms (facebook, instagram, linkedin, pinterest): the ads SocialAccount (metaads, linkedinads, pinterestads) reuses the OAuth token of the parent posting account, but only when an active parent exists and, for facebook and instagram, its stored token carries ads_management and ads_read (linkedin and pinterest need no extra scope). In that case no extra OAuth happens and the response is alreadyConnected: true. When no such parent exists, or the scopes are missing, the endpoint returns an authUrl and a full OAuth round trip is required. When a parent exists but carries no token usable for ad accounts, the call fails with 400 RECONNECT_REQUIRED. Independently of the branch, the call can return 403 ADS_ADDON_REQUIRED without the ads add-on and 402 PAYMENT_REQUIRED when the billing gate is closed. Meta Ads prerequisite: connecting Meta Ads (via facebook or instagram) requires a Facebook Page. Not because the ad account is read through a Page, but because both parent posting accounts are: the facebook flow only offers Pages you manage, and the instagram flow with loginMethod=facebook_login only offers Instagram accounts linked to one of those Pages. Without a Page there is no parent account to inherit a token from. A user who manages no Facebook Page cannot complete this connection, and the facebook flow ends with error=no_facebook_pages. Separate-token platforms (tiktok, twitter): Starts the platform-specific marketing API OAuth flow and creates an ads SocialAccount (tiktokads, xads) with its own token. If the ads account already exists, returns alreadyConnected: true. - tiktok: accountId is OPTIONAL. With accountId, the new tiktokads account links to that posting account (parentAccountId set) — Spark Ads + standalone ads using the posting TT_USER identity become available. Without accountId, ads-only mode kicks in: the new tiktokads account has parentAccountId=null and standalone ads use a synthetic CUSTOMIZED_USER (\"Brand Identity\"); Spark Ads are unavailable because TikTok requires a posting account for them. The Brand Identity is configured separately via PATCH /v1/connect/tiktok-ads (or inline on POST /v1/ads/create via the brandIdentity field). - twitter (X Ads): accountId is REQUIRED. There's no ads-only mode — tweets need to be authored by a real X user. Standalone platforms (googleads): Starts the Google Ads OAuth flow and creates a standalone ads SocialAccount (googleads) with no parent. If the account already exists, returns alreadyConnected: true. Ads accounts appear as regular SocialAccount documents with ads platform values (e.g., metaads, tiktokads) in GET /v1/accounts.
|
|
318
|
+
# @param platform [String] Platform to connect ads for. Only platforms with ads support are accepted. `instagram` requires an Instagram account connected with loginMethod=facebook_login whose token carries ads_management and ads_read. With an account connected through the default instagram_login flow no ads account can be created; do not use this value for those accounts.
|
|
319
319
|
# @param profile_id [String] Your Zernio profile ID
|
|
320
320
|
# @param [Hash] opts the optional parameters
|
|
321
321
|
# @option opts [String] :account_id Existing SocialAccount ID. Required for `twitter` (X Ads). Optional for `tiktok` — omit to enter ads-only mode (no TikTok posting account linked; ad creation uses a Brand Identity instead of a TT_USER). Ignored for same-token (`facebook`, `instagram`, `linkedin`, `pinterest`) and standalone (`googleads`) platforms.
|
|
322
|
-
# @option opts [String] :redirect_url Custom URL the browser is sent to once the OAuth flow finishes. Honored on every ads platform, including the separate-token (`tiktok`, `twitter`) and standalone (`googleads`) flows. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. On success `tiktok`, `twitter` and `googleads` land on the URL unchanged, while the same-token platforms (`facebook`, `instagram`, `linkedin`, `pinterest`) append `connected`, `profileId`, `accountId`, `username` and, on API-key calls, `connect_token`. On failure
|
|
322
|
+
# @option opts [String] :redirect_url Custom URL the browser is sent to once the OAuth flow finishes. Honored on every ads platform, including the separate-token (`tiktok`, `twitter`) and standalone (`googleads`) flows. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. On success `tiktok`, `twitter` and `googleads` land on the URL unchanged, while the same-token platforms (`facebook`, `instagram`, `linkedin`, `pinterest`) append `connected`, `profileId`, `accountId`, `username` and, on API-key calls, `connect_token`. On failure the same error contract applies as on GET /v1/connect/{platform}: `error` and `platform` are always appended, other params are optional, and the value list there is not exhaustive. Note that on the tiktok, twitter and googleads flows `platform` carries the ads platform id (`tiktokads`, `xads`, `googleads`), not the value used in the request path. When omitted, the browser lands on the Zernio dashboard.
|
|
323
323
|
# @option opts [Boolean] :headless Enable headless mode (same-token platforms only) (default to false)
|
|
324
324
|
# @option opts [Boolean] :force Force a fresh OAuth even when an account already exists. Normally the endpoint returns `alreadyConnected: true` whenever a connected account is found, keying off its active state rather than token liveness. Set `force=true` to bypass that and always receivean `authUrl`. Completing the returned OAuth refreshes the stored token on the existing posting and ads accounts in place. (default to false)
|
|
325
325
|
# @option opts [String] :ad_account_id Scope ad sync to a single platform ad account. Without this param, sync covers every ad account the connected token can see. Supported on `facebook`/`instagram` (Meta, `act_<digits>`), `linkedin` (bare numeric sponsored-account id), `googleads` (bare customer id digits) and `twitter` (X Ads, base36 account id). `tiktok` scopes advertisers at OAuth and `pinterest` has no ads discovery, so both ignore it. Meta ids are additionally validated against the connected token; unreachable IDs return 400. Setting a scope also removes already synced ads from de-scoped ad accounts. For multiple accounts use `adAccountIds` instead.
|
|
@@ -944,7 +944,7 @@ module Zernio
|
|
|
944
944
|
# @param platform [String] Social media platform to connect
|
|
945
945
|
# @param profile_id [String] Your Zernio profile ID (get from /v1/profiles). For WhatsApp, a Zernio-provisioned number can only be connected on the profile it was provisioned to; connecting from any other profile is rejected with a 409.
|
|
946
946
|
# @param [Hash] opts the optional parameters
|
|
947
|
-
# @option opts [String] :redirect_url Your custom redirect URL after connection completes. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. Result params are appended with the URL API, so an existing query string is preserved. Standard mode appends connected={platform}&profileId=X&accountId=Y&username=Z. Headless mode appends OAuth data params for platforms requiring selection (e.g. LinkedIn orgs, Facebook pages). If no selection is needed, the account is created directly and the redirect includes accountId.
|
|
947
|
+
# @option opts [String] :redirect_url Your custom redirect URL after connection completes. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. Result params are appended with the URL API, so an existing query string is preserved. Standard mode appends connected={platform}&profileId=X&accountId=Y&username=Z. Headless mode appends OAuth data params for platforms requiring selection (e.g. LinkedIn orgs, Facebook pages). If no selection is needed, the account is created directly and the redirect includes accountId. On failure, the browser is sent to the same redirect_url with `error` and `platform` appended. `error` and `platform` are always present. `error_message`, `is_user_fixable`, `reason` and `dashboard_url` are conditional and must be treated as optional. This list is NOT exhaustive and new values may be added at any time. Treat an unrecognized value as a generic failure rather than matching it exhaustively. Existing values are not renamed or removed without notice. OAuth and callback: oauth_denied, invalid_callback, invalid_state, unsupported_platform, connection_failed, internal_error, token_exchange_failed, byok_config_error, personal_account_not_supported, missing_google_permissions, platform_requires_destination, reconnect_account_mismatch, invalid_request Access and limits: profile_not_found, invalid_profile_id, access_denied, account_limit_exceeded, profile_limit_exceeded, payment_required Destination selection: no_facebook_pages, facebook_pages_error, no_google_locations, google_locations_error, google_permission_denied, no_snapchat_public_profiles, snapchat_profiles_error, discord_no_guild, slack_no_team WhatsApp: whatsapp_error, one_whatsapp_per_profile, whatsapp_number_already_connected, whatsapp_number_pinned_to_profile, connection_cancelled Google Ads (platform=googleads): google_ads_auth_failed, google_ads_invalid_state, google_ads_config_error, google_ads_token_failed, google_ads_quota_exhausted, google_ads_callback_error TikTok Ads (platform=tiktokads): tiktok_ads_auth_failed, tiktok_ads_invalid_state, tiktok_ads_access_denied, tiktok_ads_config_error, tiktok_ads_token_failed, tiktok_ads_account_not_found, tiktok_ads_callback_error X Ads (platform=xads): x_ads_denied, x_ads_auth_failed, x_ads_config_error, x_ads_account_not_found, x_ads_state_error, x_ads_token_failed, x_ads_token_missing, x_ads_callback_error Shopify (platform=shopify): shopify_auth_failed, shopify_config_error, shopify_invalid_state, shopify_invalid_hmac, shopify_invalid_shop, shopify_missing_scopes, shopify_callback_error 1. On this endpoint every upstream OAuth error is collapsed into `oauth_denied`. The provider's own value (for example Meta's `access_denied`) is not forwarded. The dedicated ads flows below are different: they use their own denial slugs and `google_ads_auth_failed` and `tiktok_ads_auth_failed` may carry the provider's raw error string in `error_message`. 2. On the tiktok and twitter ads flows `platform` carries the ads platform id (`tiktokads`, `xads`), not the value used in the request path. The googleads and shopify flows report `googleads` and `shopify`.
|
|
948
948
|
# @option opts [Boolean] :headless When true, the user is redirected to your redirect_url with raw OAuth data (code, state) instead of Zernio's default account selection UI. Use this to build a custom connect experience. (default to false)
|
|
949
949
|
# @option opts [String] :login_method Instagram only. Which of the two Instagram connection methods to use. Ignored for every other platform. `instagram_login` (the default, and what you get if you omit this): the Instagram Login dialog. The user authorizes their Instagram professional account directly, no Facebook Page required. `facebook_login`: the Facebook Login dialog, i.e. \"Instagram API with Facebook Login\". The user authorizes a Facebook Page that has a linked Instagram professional account, and every API call for that account then runs through the Page. Use this when the customer manages Instagram through a Page and expects the Facebook consent screen. Because the user has to pick which Page to connect, the callback continues at the account-selection step, `/v1/connect/instagram/select-account`. `facebook_login` supports `headless=true` like the other selection platforms: the callback redirects to your `redirect_url` with `profileId`, `tempToken`, `platform=instagram`, `step=select_account` and `connect_token`, which you pass into the select-account endpoints to finish. The default `instagram_login` has no selection step, so it connects the account directly. (default to 'instagram_login')
|
|
950
950
|
# @option opts [String] :onboarding WhatsApp only. Ignored for every other platform. Controls which screen Meta's Embedded Signup popup shows. If omitted, the connection defaults to coexistence (same as `business_app` below), preserving existing behavior for numbers already on the WhatsApp Business app. `api`: standard Embedded Signup, showing Meta's WABA/number picker. Use this to connect a phone number already on Cloud API elsewhere. `business_app`: coexistence, i.e. 'Connect existing WhatsApp Business app' (a number shared between Cloud API and the consumer WhatsApp Business app).
|
|
@@ -959,7 +959,7 @@ module Zernio
|
|
|
959
959
|
# @param platform [String] Social media platform to connect
|
|
960
960
|
# @param profile_id [String] Your Zernio profile ID (get from /v1/profiles). For WhatsApp, a Zernio-provisioned number can only be connected on the profile it was provisioned to; connecting from any other profile is rejected with a 409.
|
|
961
961
|
# @param [Hash] opts the optional parameters
|
|
962
|
-
# @option opts [String] :redirect_url Your custom redirect URL after connection completes. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. Result params are appended with the URL API, so an existing query string is preserved. Standard mode appends connected={platform}&profileId=X&accountId=Y&username=Z. Headless mode appends OAuth data params for platforms requiring selection (e.g. LinkedIn orgs, Facebook pages). If no selection is needed, the account is created directly and the redirect includes accountId.
|
|
962
|
+
# @option opts [String] :redirect_url Your custom redirect URL after connection completes. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. Result params are appended with the URL API, so an existing query string is preserved. Standard mode appends connected={platform}&profileId=X&accountId=Y&username=Z. Headless mode appends OAuth data params for platforms requiring selection (e.g. LinkedIn orgs, Facebook pages). If no selection is needed, the account is created directly and the redirect includes accountId. On failure, the browser is sent to the same redirect_url with `error` and `platform` appended. `error` and `platform` are always present. `error_message`, `is_user_fixable`, `reason` and `dashboard_url` are conditional and must be treated as optional. This list is NOT exhaustive and new values may be added at any time. Treat an unrecognized value as a generic failure rather than matching it exhaustively. Existing values are not renamed or removed without notice. OAuth and callback: oauth_denied, invalid_callback, invalid_state, unsupported_platform, connection_failed, internal_error, token_exchange_failed, byok_config_error, personal_account_not_supported, missing_google_permissions, platform_requires_destination, reconnect_account_mismatch, invalid_request Access and limits: profile_not_found, invalid_profile_id, access_denied, account_limit_exceeded, profile_limit_exceeded, payment_required Destination selection: no_facebook_pages, facebook_pages_error, no_google_locations, google_locations_error, google_permission_denied, no_snapchat_public_profiles, snapchat_profiles_error, discord_no_guild, slack_no_team WhatsApp: whatsapp_error, one_whatsapp_per_profile, whatsapp_number_already_connected, whatsapp_number_pinned_to_profile, connection_cancelled Google Ads (platform=googleads): google_ads_auth_failed, google_ads_invalid_state, google_ads_config_error, google_ads_token_failed, google_ads_quota_exhausted, google_ads_callback_error TikTok Ads (platform=tiktokads): tiktok_ads_auth_failed, tiktok_ads_invalid_state, tiktok_ads_access_denied, tiktok_ads_config_error, tiktok_ads_token_failed, tiktok_ads_account_not_found, tiktok_ads_callback_error X Ads (platform=xads): x_ads_denied, x_ads_auth_failed, x_ads_config_error, x_ads_account_not_found, x_ads_state_error, x_ads_token_failed, x_ads_token_missing, x_ads_callback_error Shopify (platform=shopify): shopify_auth_failed, shopify_config_error, shopify_invalid_state, shopify_invalid_hmac, shopify_invalid_shop, shopify_missing_scopes, shopify_callback_error 1. On this endpoint every upstream OAuth error is collapsed into `oauth_denied`. The provider's own value (for example Meta's `access_denied`) is not forwarded. The dedicated ads flows below are different: they use their own denial slugs and `google_ads_auth_failed` and `tiktok_ads_auth_failed` may carry the provider's raw error string in `error_message`. 2. On the tiktok and twitter ads flows `platform` carries the ads platform id (`tiktokads`, `xads`), not the value used in the request path. The googleads and shopify flows report `googleads` and `shopify`.
|
|
963
963
|
# @option opts [Boolean] :headless When true, the user is redirected to your redirect_url with raw OAuth data (code, state) instead of Zernio's default account selection UI. Use this to build a custom connect experience. (default to false)
|
|
964
964
|
# @option opts [String] :login_method Instagram only. Which of the two Instagram connection methods to use. Ignored for every other platform. `instagram_login` (the default, and what you get if you omit this): the Instagram Login dialog. The user authorizes their Instagram professional account directly, no Facebook Page required. `facebook_login`: the Facebook Login dialog, i.e. \"Instagram API with Facebook Login\". The user authorizes a Facebook Page that has a linked Instagram professional account, and every API call for that account then runs through the Page. Use this when the customer manages Instagram through a Page and expects the Facebook consent screen. Because the user has to pick which Page to connect, the callback continues at the account-selection step, `/v1/connect/instagram/select-account`. `facebook_login` supports `headless=true` like the other selection platforms: the callback redirects to your `redirect_url` with `profileId`, `tempToken`, `platform=instagram`, `step=select_account` and `connect_token`, which you pass into the select-account endpoints to finish. The default `instagram_login` has no selection step, so it connects the account directly. (default to 'instagram_login')
|
|
965
965
|
# @option opts [String] :onboarding WhatsApp only. Ignored for every other platform. Controls which screen Meta's Embedded Signup popup shows. If omitted, the connection defaults to coexistence (same as `business_app` below), preserving existing behavior for numbers already on the WhatsApp Business app. `api`: standard Embedded Signup, showing Meta's WABA/number picker. Use this to connect a phone number already on Cloud API elsewhere. `business_app`: coexistence, i.e. 'Connect existing WhatsApp Business app' (a number shared between Cloud API and the consumer WhatsApp Business app).
|
|
@@ -485,11 +485,11 @@ module Zernio
|
|
|
485
485
|
end
|
|
486
486
|
|
|
487
487
|
# Resolve message attachment
|
|
488
|
-
# Resolve one attachment on a message to a media url that works right now. Instagram and Facebook sign DM media urls per request and expire them, so the `url` on a message is a snapshot: it works when you read the message and stops working later. This endpoint checks the stored url and, when it has gone stale, re-mints the message's media from Meta and persists it before answering. The message id never expires, so this URL is the one to store
|
|
488
|
+
# Resolve one attachment on a message to a media url that works right now. Instagram and Facebook sign DM media urls per request and expire them, so the `url` on a message is a snapshot: it works when you read the message and stops working later. This endpoint checks the stored url and, when it has gone stale, re-mints the message's media from Meta and persists it before answering. The message id never expires, so this URL is the one to store. It is returned ready-made on each attachment as `refreshUrl` when you read a message over REST. **Webhook payloads do not carry `refreshUrl`**, so a webhook-driven integration builds this URL itself. Every piece is in the event: `message.conversationId`, `message.platformMessageId`, the attachment's zero-based position, and `account.accountId`. Note that **`accountId` is a required query parameter**; omitting it returns `400` `missing_required_field`, which is the same requirement `GET /v1/whatsapp/media/{mediaId}` has. By default it responds `302` to the live media url, so it can be used directly as an `<img src>` on a browser session. API-key integrators should pass `?format=json` and read `url` off the body, since a browser cannot attach an Authorization header to an image request. Only Instagram and Facebook media can be re-minted. On other platforms the stored url is returned as-is when it still resolves, and `404` otherwise.
|
|
489
489
|
# @param conversation_id [String] The conversation ID (Zernio id or platform conversation id)
|
|
490
490
|
# @param message_id [String] The message id as returned by the list-messages endpoint (the platform message id)
|
|
491
491
|
# @param index [Integer] Zero-based position of the attachment in the message's attachments array
|
|
492
|
-
# @param account_id [String] Social account ID
|
|
492
|
+
# @param account_id [String] Social account ID. Required: without it the request returns 400 missing_required_field.
|
|
493
493
|
# @param [Hash] opts the optional parameters
|
|
494
494
|
# @option opts [String] :format `redirect` (default) answers 302 to the media; `json` returns the url in the body (default to 'redirect')
|
|
495
495
|
# @return [GetMessageAttachment200Response]
|
|
@@ -499,11 +499,11 @@ module Zernio
|
|
|
499
499
|
end
|
|
500
500
|
|
|
501
501
|
# Resolve message attachment
|
|
502
|
-
# Resolve one attachment on a message to a media url that works right now. Instagram and Facebook sign DM media urls per request and expire them, so the `url` on a message is a snapshot: it works when you read the message and stops working later. This endpoint checks the stored url and, when it has gone stale, re-mints the message's media from Meta and persists it before answering. The message id never expires, so this URL is the one to store
|
|
502
|
+
# Resolve one attachment on a message to a media url that works right now. Instagram and Facebook sign DM media urls per request and expire them, so the `url` on a message is a snapshot: it works when you read the message and stops working later. This endpoint checks the stored url and, when it has gone stale, re-mints the message's media from Meta and persists it before answering. The message id never expires, so this URL is the one to store. It is returned ready-made on each attachment as `refreshUrl` when you read a message over REST. **Webhook payloads do not carry `refreshUrl`**, so a webhook-driven integration builds this URL itself. Every piece is in the event: `message.conversationId`, `message.platformMessageId`, the attachment's zero-based position, and `account.accountId`. Note that **`accountId` is a required query parameter**; omitting it returns `400` `missing_required_field`, which is the same requirement `GET /v1/whatsapp/media/{mediaId}` has. By default it responds `302` to the live media url, so it can be used directly as an `<img src>` on a browser session. API-key integrators should pass `?format=json` and read `url` off the body, since a browser cannot attach an Authorization header to an image request. Only Instagram and Facebook media can be re-minted. On other platforms the stored url is returned as-is when it still resolves, and `404` otherwise.
|
|
503
503
|
# @param conversation_id [String] The conversation ID (Zernio id or platform conversation id)
|
|
504
504
|
# @param message_id [String] The message id as returned by the list-messages endpoint (the platform message id)
|
|
505
505
|
# @param index [Integer] Zero-based position of the attachment in the message's attachments array
|
|
506
|
-
# @param account_id [String] Social account ID
|
|
506
|
+
# @param account_id [String] Social account ID. Required: without it the request returns 400 missing_required_field.
|
|
507
507
|
# @param [Hash] opts the optional parameters
|
|
508
508
|
# @option opts [String] :format `redirect` (default) answers 302 to the media; `json` returns the url in the body (default to 'redirect')
|
|
509
509
|
# @return [Array<(GetMessageAttachment200Response, Integer, Hash)>] GetMessageAttachment200Response data, response status code and response headers
|
|
@@ -19,6 +19,9 @@ module Zernio
|
|
|
19
19
|
|
|
20
20
|
attr_accessor :type
|
|
21
21
|
|
|
22
|
+
# Instagram and Facebook only, and present only when it differs from `type`. Meta's own type before normalization: `ig_reel` and `reel` become `video`, while `ig_post`, `post`, `ig_story` and `story_mention` become `share`. A story mention is `type: \"share\"` with `originalType: \"story_mention\"`; render on this field, since `share` alone is ambiguous.
|
|
23
|
+
attr_accessor :original_type
|
|
24
|
+
|
|
22
25
|
# Direct media link. On Instagram and Facebook this is a signed Meta CDN url that EXPIRES: use it now, do not store it. Persist `refreshUrl` instead.
|
|
23
26
|
attr_accessor :url
|
|
24
27
|
|
|
@@ -56,6 +59,7 @@ module Zernio
|
|
|
56
59
|
{
|
|
57
60
|
:'id' => :'id',
|
|
58
61
|
:'type' => :'type',
|
|
62
|
+
:'original_type' => :'originalType',
|
|
59
63
|
:'url' => :'url',
|
|
60
64
|
:'refresh_url' => :'refreshUrl',
|
|
61
65
|
:'filename' => :'filename',
|
|
@@ -78,6 +82,7 @@ module Zernio
|
|
|
78
82
|
{
|
|
79
83
|
:'id' => :'String',
|
|
80
84
|
:'type' => :'String',
|
|
85
|
+
:'original_type' => :'String',
|
|
81
86
|
:'url' => :'String',
|
|
82
87
|
:'refresh_url' => :'String',
|
|
83
88
|
:'filename' => :'String',
|
|
@@ -118,6 +123,10 @@ module Zernio
|
|
|
118
123
|
self.type = attributes[:'type']
|
|
119
124
|
end
|
|
120
125
|
|
|
126
|
+
if attributes.key?(:'original_type')
|
|
127
|
+
self.original_type = attributes[:'original_type']
|
|
128
|
+
end
|
|
129
|
+
|
|
121
130
|
if attributes.key?(:'url')
|
|
122
131
|
self.url = attributes[:'url']
|
|
123
132
|
end
|
|
@@ -169,6 +178,7 @@ module Zernio
|
|
|
169
178
|
self.class == o.class &&
|
|
170
179
|
id == o.id &&
|
|
171
180
|
type == o.type &&
|
|
181
|
+
original_type == o.original_type &&
|
|
172
182
|
url == o.url &&
|
|
173
183
|
refresh_url == o.refresh_url &&
|
|
174
184
|
filename == o.filename &&
|
|
@@ -184,7 +194,7 @@ module Zernio
|
|
|
184
194
|
# Calculates hash code according to all attributes.
|
|
185
195
|
# @return [Integer] Hash code
|
|
186
196
|
def hash
|
|
187
|
-
[id, type, url, refresh_url, filename, preview_url].hash
|
|
197
|
+
[id, type, original_type, url, refresh_url, filename, preview_url].hash
|
|
188
198
|
end
|
|
189
199
|
|
|
190
200
|
# Builds the object from hash
|
|
@@ -15,10 +15,13 @@ require 'time'
|
|
|
15
15
|
|
|
16
16
|
module Zernio
|
|
17
17
|
class WebhookPayloadMessageMessageAttachmentsInner < ApiModelBase
|
|
18
|
-
# Attachment type (image, video, file, sticker, audio)
|
|
18
|
+
# Attachment type (image, video, file, sticker, audio, share)
|
|
19
19
|
attr_accessor :type
|
|
20
20
|
|
|
21
|
-
#
|
|
21
|
+
# Instagram and Facebook only, and present only when it differs from `type`. Meta's own attachment type before Zernio normalized it: `ig_reel` and `reel` become `video`, while `ig_post`, `post`, `ig_story` and `story_mention` all become `share`. Read it before rendering, because `type: \"share\"` alone is ambiguous. In particular a story mention arrives as `type: \"share\"` with `originalType: \"story_mention\"`; treating an unrecognized type as a generic document shows your agent \"document received\" for what is usually a lead.
|
|
22
|
+
attr_accessor :original_type
|
|
23
|
+
|
|
24
|
+
# Where to fetch the attachment. **The contract differs by platform.** - **WhatsApp**: points at `GET /v1/whatsapp/media/{mediaId}`, an authenticated Zernio endpoint. You MUST send `Authorization: Bearer <your API key>`; fetching it without that header returns `401`. Download and store the bytes when this webhook arrives: Meta drops inbound media after a limited retention window, after which the endpoint answers `400` permanently and the media is unrecoverable. - **Instagram / Facebook / Telegram**: a direct platform CDN link that needs no authentication and expires on the platform's own schedule. **Webhook attachments carry no `refreshUrl`.** That field is stamped only when you read a message back over REST (`GET /v1/inbox/conversations/{conversationId}/messages`). On Instagram and Facebook the url above is a signed Meta CDN link that expires, so do not persist it: store the message id and resolve the media through `GET /v1/inbox/conversations/{conversationId}/messages/{messageId}/attachments/{index}?accountId={accountId}`, which re-mints it on demand. Every value that URL needs is already in this payload: `message.conversationId`, `message.platformMessageId`, `account.accountId`, and the attachment's zero-based position in this array.
|
|
22
25
|
attr_accessor :url
|
|
23
26
|
|
|
24
27
|
# Additional attachment metadata
|
|
@@ -28,6 +31,7 @@ module Zernio
|
|
|
28
31
|
def self.attribute_map
|
|
29
32
|
{
|
|
30
33
|
:'type' => :'type',
|
|
34
|
+
:'original_type' => :'originalType',
|
|
31
35
|
:'url' => :'url',
|
|
32
36
|
:'payload' => :'payload'
|
|
33
37
|
}
|
|
@@ -47,6 +51,7 @@ module Zernio
|
|
|
47
51
|
def self.openapi_types
|
|
48
52
|
{
|
|
49
53
|
:'type' => :'String',
|
|
54
|
+
:'original_type' => :'String',
|
|
50
55
|
:'url' => :'String',
|
|
51
56
|
:'payload' => :'Object'
|
|
52
57
|
}
|
|
@@ -80,6 +85,10 @@ module Zernio
|
|
|
80
85
|
self.type = nil
|
|
81
86
|
end
|
|
82
87
|
|
|
88
|
+
if attributes.key?(:'original_type')
|
|
89
|
+
self.original_type = attributes[:'original_type']
|
|
90
|
+
end
|
|
91
|
+
|
|
83
92
|
if attributes.key?(:'url')
|
|
84
93
|
self.url = attributes[:'url']
|
|
85
94
|
else
|
|
@@ -142,6 +151,7 @@ module Zernio
|
|
|
142
151
|
return true if self.equal?(o)
|
|
143
152
|
self.class == o.class &&
|
|
144
153
|
type == o.type &&
|
|
154
|
+
original_type == o.original_type &&
|
|
145
155
|
url == o.url &&
|
|
146
156
|
payload == o.payload
|
|
147
157
|
end
|
|
@@ -155,7 +165,7 @@ module Zernio
|
|
|
155
165
|
# Calculates hash code according to all attributes.
|
|
156
166
|
# @return [Integer] Hash code
|
|
157
167
|
def hash
|
|
158
|
-
[type, url, payload].hash
|
|
168
|
+
[type, original_type, url, payload].hash
|
|
159
169
|
end
|
|
160
170
|
|
|
161
171
|
# Builds the object from hash
|
|
@@ -15,10 +15,13 @@ require 'time'
|
|
|
15
15
|
|
|
16
16
|
module Zernio
|
|
17
17
|
class WebhookPayloadMessageSentMessageAttachmentsInner < ApiModelBase
|
|
18
|
-
# Attachment type (image, video, file, sticker, audio)
|
|
18
|
+
# Attachment type (image, video, file, sticker, audio, share)
|
|
19
19
|
attr_accessor :type
|
|
20
20
|
|
|
21
|
-
#
|
|
21
|
+
# Instagram and Facebook only, and present only when it differs from `type`. Meta's own attachment type before Zernio normalized it. See the same field on message.received for the full mapping.
|
|
22
|
+
attr_accessor :original_type
|
|
23
|
+
|
|
24
|
+
# Where to fetch the attachment. For outgoing messages this is the media URL as sent, so for WhatsApp it is the URL you supplied when publishing (WhatsApp sends media by link), not a Zernio endpoint, and it needs no Zernio credentials. Contrast the inbound direction: `message.received` attachment URLs on WhatsApp point at the authenticated `GET /v1/whatsapp/media/{mediaId}`. As on `message.received`, webhook attachments carry no `refreshUrl`: that field is stamped only on the REST read. Resolve Instagram and Facebook media through `GET /v1/inbox/conversations/{conversationId}/messages/{messageId}/attachments/{index}?accountId={accountId}`.
|
|
22
25
|
attr_accessor :url
|
|
23
26
|
|
|
24
27
|
# Additional attachment metadata
|
|
@@ -28,6 +31,7 @@ module Zernio
|
|
|
28
31
|
def self.attribute_map
|
|
29
32
|
{
|
|
30
33
|
:'type' => :'type',
|
|
34
|
+
:'original_type' => :'originalType',
|
|
31
35
|
:'url' => :'url',
|
|
32
36
|
:'payload' => :'payload'
|
|
33
37
|
}
|
|
@@ -47,6 +51,7 @@ module Zernio
|
|
|
47
51
|
def self.openapi_types
|
|
48
52
|
{
|
|
49
53
|
:'type' => :'String',
|
|
54
|
+
:'original_type' => :'String',
|
|
50
55
|
:'url' => :'String',
|
|
51
56
|
:'payload' => :'Object'
|
|
52
57
|
}
|
|
@@ -80,6 +85,10 @@ module Zernio
|
|
|
80
85
|
self.type = nil
|
|
81
86
|
end
|
|
82
87
|
|
|
88
|
+
if attributes.key?(:'original_type')
|
|
89
|
+
self.original_type = attributes[:'original_type']
|
|
90
|
+
end
|
|
91
|
+
|
|
83
92
|
if attributes.key?(:'url')
|
|
84
93
|
self.url = attributes[:'url']
|
|
85
94
|
else
|
|
@@ -142,6 +151,7 @@ module Zernio
|
|
|
142
151
|
return true if self.equal?(o)
|
|
143
152
|
self.class == o.class &&
|
|
144
153
|
type == o.type &&
|
|
154
|
+
original_type == o.original_type &&
|
|
145
155
|
url == o.url &&
|
|
146
156
|
payload == o.payload
|
|
147
157
|
end
|
|
@@ -155,7 +165,7 @@ module Zernio
|
|
|
155
165
|
# Calculates hash code according to all attributes.
|
|
156
166
|
# @return [Integer] Hash code
|
|
157
167
|
def hash
|
|
158
|
-
[type, url, payload].hash
|
|
168
|
+
[type, original_type, url, payload].hash
|
|
159
169
|
end
|
|
160
170
|
|
|
161
171
|
# Builds the object from hash
|
|
@@ -14,16 +14,21 @@ require 'date'
|
|
|
14
14
|
require 'time'
|
|
15
15
|
|
|
16
16
|
module Zernio
|
|
17
|
+
# **On this event the sender is your own business, not the person you are talking to.** `id` is the Zernio account id and `name`, `username` and `picture` are that connected account's own profile. Do not read these to name or update a contact: doing so on an echo relabels the customer's record with your business name. The other party is `conversation.participantId` / `participantName` / `participantUsername`, which are populated in both directions.
|
|
17
18
|
class WebhookPayloadMessageSentMessageSender < ApiModelBase
|
|
19
|
+
# The Zernio account id of the connected account that sent the message, not a contact id.
|
|
18
20
|
attr_accessor :id
|
|
19
21
|
|
|
20
22
|
# Always omitted on this event: the sender is the business, not a contact. Use conversation.contactId to join back to the CRM Contact.
|
|
21
23
|
attr_accessor :contact_id
|
|
22
24
|
|
|
25
|
+
# Display name of your connected account.
|
|
23
26
|
attr_accessor :name
|
|
24
27
|
|
|
28
|
+
# Username of your connected account.
|
|
25
29
|
attr_accessor :username
|
|
26
30
|
|
|
31
|
+
# Profile picture of your connected account.
|
|
27
32
|
attr_accessor :picture
|
|
28
33
|
|
|
29
34
|
# Attribute mapping from ruby-style variable name to JSON key.
|
data/lib/zernio-sdk/version.rb
CHANGED
data/openapi.yaml
CHANGED
|
@@ -3613,7 +3613,20 @@ components:
|
|
|
3613
3613
|
properties:
|
|
3614
3614
|
type:
|
|
3615
3615
|
type: string
|
|
3616
|
-
description: Attachment type (image, video, file, sticker, audio)
|
|
3616
|
+
description: Attachment type (image, video, file, sticker, audio, share)
|
|
3617
|
+
originalType:
|
|
3618
|
+
type: string
|
|
3619
|
+
description: |
|
|
3620
|
+
Instagram and Facebook only, and present only when it differs
|
|
3621
|
+
from `type`. Meta's own attachment type before Zernio normalized
|
|
3622
|
+
it: `ig_reel` and `reel` become `video`, while `ig_post`, `post`,
|
|
3623
|
+
`ig_story` and `story_mention` all become `share`.
|
|
3624
|
+
|
|
3625
|
+
Read it before rendering, because `type: "share"` alone is
|
|
3626
|
+
ambiguous. In particular a story mention arrives as
|
|
3627
|
+
`type: "share"` with `originalType: "story_mention"`; treating an
|
|
3628
|
+
unrecognized type as a generic document shows your agent
|
|
3629
|
+
"document received" for what is usually a lead.
|
|
3617
3630
|
url:
|
|
3618
3631
|
type: string
|
|
3619
3632
|
description: |
|
|
@@ -3629,6 +3642,18 @@ components:
|
|
|
3629
3642
|
- **Instagram / Facebook / Telegram**: a direct platform CDN link
|
|
3630
3643
|
that needs no authentication and expires on the platform's own
|
|
3631
3644
|
schedule.
|
|
3645
|
+
|
|
3646
|
+
**Webhook attachments carry no `refreshUrl`.** That field is
|
|
3647
|
+
stamped only when you read a message back over REST
|
|
3648
|
+
(`GET /v1/inbox/conversations/{conversationId}/messages`). On
|
|
3649
|
+
Instagram and Facebook the url above is a signed Meta CDN link
|
|
3650
|
+
that expires, so do not persist it: store the message id and
|
|
3651
|
+
resolve the media through
|
|
3652
|
+
`GET /v1/inbox/conversations/{conversationId}/messages/{messageId}/attachments/{index}?accountId={accountId}`,
|
|
3653
|
+
which re-mints it on demand. Every value that URL needs is
|
|
3654
|
+
already in this payload: `message.conversationId`,
|
|
3655
|
+
`message.platformMessageId`, `account.accountId`, and the
|
|
3656
|
+
attachment's zero-based position in this array.
|
|
3632
3657
|
payload:
|
|
3633
3658
|
type: object
|
|
3634
3659
|
description: Additional attachment metadata
|
|
@@ -4031,7 +4056,10 @@ components:
|
|
|
4031
4056
|
properties:
|
|
4032
4057
|
type:
|
|
4033
4058
|
type: string
|
|
4034
|
-
description: Attachment type (image, video, file, sticker, audio)
|
|
4059
|
+
description: Attachment type (image, video, file, sticker, audio, share)
|
|
4060
|
+
originalType:
|
|
4061
|
+
type: string
|
|
4062
|
+
description: 'Instagram and Facebook only, and present only when it differs from `type`. Meta''s own attachment type before Zernio normalized it. See the same field on message.received for the full mapping.'
|
|
4035
4063
|
url:
|
|
4036
4064
|
type: string
|
|
4037
4065
|
description: |
|
|
@@ -4041,24 +4069,42 @@ components:
|
|
|
4041
4069
|
and it needs no Zernio credentials. Contrast the inbound direction:
|
|
4042
4070
|
`message.received` attachment URLs on WhatsApp point at the
|
|
4043
4071
|
authenticated `GET /v1/whatsapp/media/{mediaId}`.
|
|
4072
|
+
|
|
4073
|
+
As on `message.received`, webhook attachments carry no
|
|
4074
|
+
`refreshUrl`: that field is stamped only on the REST read. Resolve
|
|
4075
|
+
Instagram and Facebook media through
|
|
4076
|
+
`GET /v1/inbox/conversations/{conversationId}/messages/{messageId}/attachments/{index}?accountId={accountId}`.
|
|
4044
4077
|
payload:
|
|
4045
4078
|
type: object
|
|
4046
4079
|
description: Additional attachment metadata
|
|
4047
4080
|
sender:
|
|
4048
4081
|
type: object
|
|
4049
4082
|
required: [id]
|
|
4083
|
+
description: |
|
|
4084
|
+
**On this event the sender is your own business, not the person you
|
|
4085
|
+
are talking to.** `id` is the Zernio account id and `name`,
|
|
4086
|
+
`username` and `picture` are that connected account's own profile.
|
|
4087
|
+
|
|
4088
|
+
Do not read these to name or update a contact: doing so on an echo
|
|
4089
|
+
relabels the customer's record with your business name. The other
|
|
4090
|
+
party is `conversation.participantId` / `participantName` /
|
|
4091
|
+
`participantUsername`, which are populated in both directions.
|
|
4050
4092
|
properties:
|
|
4051
4093
|
id:
|
|
4052
4094
|
type: string
|
|
4095
|
+
description: 'The Zernio account id of the connected account that sent the message, not a contact id.'
|
|
4053
4096
|
contactId:
|
|
4054
4097
|
type: string
|
|
4055
4098
|
description: 'Always omitted on this event: the sender is the business, not a contact. Use conversation.contactId to join back to the CRM Contact.'
|
|
4056
4099
|
name:
|
|
4057
4100
|
type: string
|
|
4101
|
+
description: Display name of your connected account.
|
|
4058
4102
|
username:
|
|
4059
4103
|
type: string
|
|
4104
|
+
description: Username of your connected account.
|
|
4060
4105
|
picture:
|
|
4061
4106
|
type: string
|
|
4107
|
+
description: Profile picture of your connected account.
|
|
4062
4108
|
sentAt:
|
|
4063
4109
|
type: string
|
|
4064
4110
|
format: date-time
|
|
@@ -17312,7 +17358,61 @@ paths:
|
|
|
17312
17358
|
- name: redirect_url
|
|
17313
17359
|
in: query
|
|
17314
17360
|
schema: { type: string, format: uri }
|
|
17315
|
-
description:
|
|
17361
|
+
description: |
|
|
17362
|
+
Your custom redirect URL after connection completes. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. Result params are appended with the URL API, so an existing query string is preserved. Standard mode appends connected={platform}&profileId=X&accountId=Y&username=Z. Headless mode appends OAuth data params for platforms requiring selection (e.g. LinkedIn orgs, Facebook pages). If no selection is needed, the account is created directly and the redirect includes accountId.
|
|
17363
|
+
|
|
17364
|
+
On failure, the browser is sent to the same redirect_url with `error` and `platform` appended.
|
|
17365
|
+
`error` and `platform` are always present. `error_message`, `is_user_fixable`, `reason` and
|
|
17366
|
+
`dashboard_url` are conditional and must be treated as optional.
|
|
17367
|
+
|
|
17368
|
+
This list is NOT exhaustive and new values may be added at any time. Treat an unrecognized
|
|
17369
|
+
value as a generic failure rather than matching it exhaustively. Existing values are not
|
|
17370
|
+
renamed or removed without notice.
|
|
17371
|
+
|
|
17372
|
+
OAuth and callback:
|
|
17373
|
+
oauth_denied, invalid_callback, invalid_state, unsupported_platform, connection_failed,
|
|
17374
|
+
internal_error, token_exchange_failed, byok_config_error, personal_account_not_supported,
|
|
17375
|
+
missing_google_permissions, platform_requires_destination, reconnect_account_mismatch,
|
|
17376
|
+
invalid_request
|
|
17377
|
+
|
|
17378
|
+
Access and limits:
|
|
17379
|
+
profile_not_found, invalid_profile_id, access_denied, account_limit_exceeded,
|
|
17380
|
+
profile_limit_exceeded, payment_required
|
|
17381
|
+
|
|
17382
|
+
Destination selection:
|
|
17383
|
+
no_facebook_pages, facebook_pages_error, no_google_locations, google_locations_error,
|
|
17384
|
+
google_permission_denied, no_snapchat_public_profiles, snapchat_profiles_error,
|
|
17385
|
+
discord_no_guild, slack_no_team
|
|
17386
|
+
|
|
17387
|
+
WhatsApp:
|
|
17388
|
+
whatsapp_error, one_whatsapp_per_profile, whatsapp_number_already_connected,
|
|
17389
|
+
whatsapp_number_pinned_to_profile, connection_cancelled
|
|
17390
|
+
|
|
17391
|
+
Google Ads (platform=googleads):
|
|
17392
|
+
google_ads_auth_failed, google_ads_invalid_state, google_ads_config_error,
|
|
17393
|
+
google_ads_token_failed, google_ads_quota_exhausted, google_ads_callback_error
|
|
17394
|
+
|
|
17395
|
+
TikTok Ads (platform=tiktokads):
|
|
17396
|
+
tiktok_ads_auth_failed, tiktok_ads_invalid_state, tiktok_ads_access_denied,
|
|
17397
|
+
tiktok_ads_config_error, tiktok_ads_token_failed, tiktok_ads_account_not_found,
|
|
17398
|
+
tiktok_ads_callback_error
|
|
17399
|
+
|
|
17400
|
+
X Ads (platform=xads):
|
|
17401
|
+
x_ads_denied, x_ads_auth_failed, x_ads_config_error, x_ads_account_not_found,
|
|
17402
|
+
x_ads_state_error, x_ads_token_failed, x_ads_token_missing, x_ads_callback_error
|
|
17403
|
+
|
|
17404
|
+
Shopify (platform=shopify):
|
|
17405
|
+
shopify_auth_failed, shopify_config_error, shopify_invalid_state, shopify_invalid_hmac,
|
|
17406
|
+
shopify_invalid_shop, shopify_missing_scopes, shopify_callback_error
|
|
17407
|
+
|
|
17408
|
+
1. On this endpoint every upstream OAuth error is collapsed into `oauth_denied`. The
|
|
17409
|
+
provider's own value (for example Meta's `access_denied`) is not forwarded. The dedicated
|
|
17410
|
+
ads flows below are different: they use their own denial slugs and `google_ads_auth_failed`
|
|
17411
|
+
and `tiktok_ads_auth_failed` may carry the provider's raw error string in `error_message`.
|
|
17412
|
+
|
|
17413
|
+
2. On the tiktok and twitter ads flows `platform` carries the ads platform id
|
|
17414
|
+
(`tiktokads`, `xads`), not the value used in the request path. The googleads and shopify
|
|
17415
|
+
flows report `googleads` and `shopify`.
|
|
17316
17416
|
- name: headless
|
|
17317
17417
|
in: query
|
|
17318
17418
|
schema: { type: boolean, default: false }
|
|
@@ -17417,7 +17517,24 @@ paths:
|
|
|
17417
17517
|
description: |
|
|
17418
17518
|
Unified ads connection endpoint. Creates a dedicated ads SocialAccount for the specified platform.
|
|
17419
17519
|
|
|
17420
|
-
Same-token platforms (facebook, instagram, linkedin, pinterest):
|
|
17520
|
+
Same-token platforms (facebook, instagram, linkedin, pinterest): the ads SocialAccount
|
|
17521
|
+
(metaads, linkedinads, pinterestads) reuses the OAuth token of the parent posting account,
|
|
17522
|
+
but only when an active parent exists and, for facebook and instagram, its stored token
|
|
17523
|
+
carries ads_management and ads_read (linkedin and pinterest need no extra scope). In that
|
|
17524
|
+
case no extra OAuth happens and the response is alreadyConnected: true. When no such parent
|
|
17525
|
+
exists, or the scopes are missing, the endpoint returns an authUrl and a full OAuth round
|
|
17526
|
+
trip is required. When a parent exists but carries no token usable for ad accounts, the call
|
|
17527
|
+
fails with 400 RECONNECT_REQUIRED. Independently of the branch, the call can return 403
|
|
17528
|
+
ADS_ADDON_REQUIRED without the ads add-on and 402 PAYMENT_REQUIRED when the billing gate is
|
|
17529
|
+
closed.
|
|
17530
|
+
|
|
17531
|
+
Meta Ads prerequisite: connecting Meta Ads (via facebook or instagram) requires a Facebook
|
|
17532
|
+
Page. Not because the ad account is read through a Page, but because both parent posting
|
|
17533
|
+
accounts are: the facebook flow only offers Pages you manage, and the instagram flow with
|
|
17534
|
+
loginMethod=facebook_login only offers Instagram accounts linked to one of those Pages.
|
|
17535
|
+
Without a Page there is no parent account to inherit a token from. A user who manages no
|
|
17536
|
+
Facebook Page cannot complete this connection, and the facebook flow ends with
|
|
17537
|
+
error=no_facebook_pages.
|
|
17421
17538
|
|
|
17422
17539
|
Separate-token platforms (tiktok, twitter): Starts the platform-specific marketing API OAuth flow and creates an ads SocialAccount (tiktokads, xads) with its own token. If the ads account already exists, returns alreadyConnected: true.
|
|
17423
17540
|
- tiktok: accountId is OPTIONAL. With accountId, the new tiktokads account links to that posting account (parentAccountId set) — Spark Ads + standalone ads using the posting TT_USER identity become available. Without accountId, ads-only mode kicks in: the new tiktokads account has parentAccountId=null and standalone ads use a synthetic CUSTOMIZED_USER ("Brand Identity"); Spark Ads are unavailable because TikTok requires a posting account for them. The Brand Identity is configured separately via PATCH /v1/connect/tiktok-ads (or inline on POST /v1/ads/create via the brandIdentity field).
|
|
@@ -17433,7 +17550,12 @@ paths:
|
|
|
17433
17550
|
schema:
|
|
17434
17551
|
type: string
|
|
17435
17552
|
enum: [facebook, instagram, linkedin, tiktok, twitter, pinterest, googleads]
|
|
17436
|
-
description:
|
|
17553
|
+
description: |
|
|
17554
|
+
Platform to connect ads for. Only platforms with ads support are accepted.
|
|
17555
|
+
|
|
17556
|
+
`instagram` requires an Instagram account connected with loginMethod=facebook_login whose
|
|
17557
|
+
token carries ads_management and ads_read. With an account connected through the default
|
|
17558
|
+
instagram_login flow no ads account can be created; do not use this value for those accounts.
|
|
17437
17559
|
- name: profileId
|
|
17438
17560
|
in: query
|
|
17439
17561
|
required: true
|
|
@@ -17458,8 +17580,12 @@ paths:
|
|
|
17458
17580
|
`tiktok`, `twitter` and `googleads` land on the URL unchanged, while the
|
|
17459
17581
|
same-token platforms (`facebook`, `instagram`, `linkedin`, `pinterest`)
|
|
17460
17582
|
append `connected`, `profileId`, `accountId`, `username` and, on API-key
|
|
17461
|
-
calls, `connect_token`. On failure
|
|
17462
|
-
|
|
17583
|
+
calls, `connect_token`. On failure the same error contract applies as on
|
|
17584
|
+
GET /v1/connect/{platform}: `error` and `platform` are always appended,
|
|
17585
|
+
other params are optional, and the value list there is not exhaustive.
|
|
17586
|
+
Note that on the tiktok, twitter and googleads flows `platform` carries
|
|
17587
|
+
the ads platform id (`tiktokads`, `xads`, `googleads`), not the value
|
|
17588
|
+
used in the request path. When omitted, the browser lands on
|
|
17463
17589
|
the Zernio dashboard.
|
|
17464
17590
|
- name: headless
|
|
17465
17591
|
in: query
|
|
@@ -26734,6 +26860,9 @@ paths:
|
|
|
26734
26860
|
properties:
|
|
26735
26861
|
id: { type: string }
|
|
26736
26862
|
type: { type: string, enum: [image, video, audio, file, sticker, share] }
|
|
26863
|
+
originalType:
|
|
26864
|
+
type: string
|
|
26865
|
+
description: 'Instagram and Facebook only, and present only when it differs from `type`. Meta''s own type before normalization: `ig_reel` and `reel` become `video`, while `ig_post`, `post`, `ig_story` and `story_mention` become `share`. A story mention is `type: "share"` with `originalType: "story_mention"`; render on this field, since `share` alone is ambiguous.'
|
|
26737
26866
|
url:
|
|
26738
26867
|
type: string
|
|
26739
26868
|
description: 'Direct media link. On Instagram and Facebook this is a signed Meta CDN url that EXPIRES: use it now, do not store it. Persist `refreshUrl` instead.'
|
|
@@ -28156,7 +28285,16 @@ paths:
|
|
|
28156
28285
|
and stops working later. This endpoint checks the stored url and, when it
|
|
28157
28286
|
has gone stale, re-mints the message's media from Meta and persists it
|
|
28158
28287
|
before answering. The message id never expires, so this URL is the one to
|
|
28159
|
-
store
|
|
28288
|
+
store. It is returned ready-made on each attachment as `refreshUrl` when
|
|
28289
|
+
you read a message over REST.
|
|
28290
|
+
|
|
28291
|
+
**Webhook payloads do not carry `refreshUrl`**, so a webhook-driven
|
|
28292
|
+
integration builds this URL itself. Every piece is in the event:
|
|
28293
|
+
`message.conversationId`, `message.platformMessageId`, the attachment's
|
|
28294
|
+
zero-based position, and `account.accountId`. Note that **`accountId` is a
|
|
28295
|
+
required query parameter**; omitting it returns `400`
|
|
28296
|
+
`missing_required_field`, which is the same requirement
|
|
28297
|
+
`GET /v1/whatsapp/media/{mediaId}` has.
|
|
28160
28298
|
|
|
28161
28299
|
By default it responds `302` to the live media url, so it can be used
|
|
28162
28300
|
directly as an `<img src>` on a browser session. API-key integrators
|
|
@@ -28188,7 +28326,7 @@ paths:
|
|
|
28188
28326
|
in: query
|
|
28189
28327
|
required: true
|
|
28190
28328
|
schema: { type: string }
|
|
28191
|
-
description: Social account ID
|
|
28329
|
+
description: 'Social account ID. Required: without it the request returns 400 missing_required_field.'
|
|
28192
28330
|
- name: format
|
|
28193
28331
|
in: query
|
|
28194
28332
|
required: false
|
|
@@ -84,12 +84,12 @@ describe 'ConnectApi' do
|
|
|
84
84
|
|
|
85
85
|
# unit tests for connect_ads
|
|
86
86
|
# Connect ads for a platform
|
|
87
|
-
# Unified ads connection endpoint. Creates a dedicated ads SocialAccount for the specified platform. Same-token platforms (facebook, instagram, linkedin, pinterest):
|
|
88
|
-
# @param platform Platform to connect ads for. Only platforms with ads support are accepted.
|
|
87
|
+
# Unified ads connection endpoint. Creates a dedicated ads SocialAccount for the specified platform. Same-token platforms (facebook, instagram, linkedin, pinterest): the ads SocialAccount (metaads, linkedinads, pinterestads) reuses the OAuth token of the parent posting account, but only when an active parent exists and, for facebook and instagram, its stored token carries ads_management and ads_read (linkedin and pinterest need no extra scope). In that case no extra OAuth happens and the response is alreadyConnected: true. When no such parent exists, or the scopes are missing, the endpoint returns an authUrl and a full OAuth round trip is required. When a parent exists but carries no token usable for ad accounts, the call fails with 400 RECONNECT_REQUIRED. Independently of the branch, the call can return 403 ADS_ADDON_REQUIRED without the ads add-on and 402 PAYMENT_REQUIRED when the billing gate is closed. Meta Ads prerequisite: connecting Meta Ads (via facebook or instagram) requires a Facebook Page. Not because the ad account is read through a Page, but because both parent posting accounts are: the facebook flow only offers Pages you manage, and the instagram flow with loginMethod=facebook_login only offers Instagram accounts linked to one of those Pages. Without a Page there is no parent account to inherit a token from. A user who manages no Facebook Page cannot complete this connection, and the facebook flow ends with error=no_facebook_pages. Separate-token platforms (tiktok, twitter): Starts the platform-specific marketing API OAuth flow and creates an ads SocialAccount (tiktokads, xads) with its own token. If the ads account already exists, returns alreadyConnected: true. - tiktok: accountId is OPTIONAL. With accountId, the new tiktokads account links to that posting account (parentAccountId set) — Spark Ads + standalone ads using the posting TT_USER identity become available. Without accountId, ads-only mode kicks in: the new tiktokads account has parentAccountId=null and standalone ads use a synthetic CUSTOMIZED_USER (\"Brand Identity\"); Spark Ads are unavailable because TikTok requires a posting account for them. The Brand Identity is configured separately via PATCH /v1/connect/tiktok-ads (or inline on POST /v1/ads/create via the brandIdentity field). - twitter (X Ads): accountId is REQUIRED. There's no ads-only mode — tweets need to be authored by a real X user. Standalone platforms (googleads): Starts the Google Ads OAuth flow and creates a standalone ads SocialAccount (googleads) with no parent. If the account already exists, returns alreadyConnected: true. Ads accounts appear as regular SocialAccount documents with ads platform values (e.g., metaads, tiktokads) in GET /v1/accounts.
|
|
88
|
+
# @param platform Platform to connect ads for. Only platforms with ads support are accepted. `instagram` requires an Instagram account connected with loginMethod=facebook_login whose token carries ads_management and ads_read. With an account connected through the default instagram_login flow no ads account can be created; do not use this value for those accounts.
|
|
89
89
|
# @param profile_id Your Zernio profile ID
|
|
90
90
|
# @param [Hash] opts the optional parameters
|
|
91
91
|
# @option opts [String] :account_id Existing SocialAccount ID. Required for `twitter` (X Ads). Optional for `tiktok` — omit to enter ads-only mode (no TikTok posting account linked; ad creation uses a Brand Identity instead of a TT_USER). Ignored for same-token (`facebook`, `instagram`, `linkedin`, `pinterest`) and standalone (`googleads`) platforms.
|
|
92
|
-
# @option opts [String] :redirect_url Custom URL the browser is sent to once the OAuth flow finishes. Honored on every ads platform, including the separate-token (`tiktok`, `twitter`) and standalone (`googleads`) flows. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. On success `tiktok`, `twitter` and `googleads` land on the URL unchanged, while the same-token platforms (`facebook`, `instagram`, `linkedin`, `pinterest`) append `connected`, `profileId`, `accountId`, `username` and, on API-key calls, `connect_token`. On failure
|
|
92
|
+
# @option opts [String] :redirect_url Custom URL the browser is sent to once the OAuth flow finishes. Honored on every ads platform, including the separate-token (`tiktok`, `twitter`) and standalone (`googleads`) flows. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. On success `tiktok`, `twitter` and `googleads` land on the URL unchanged, while the same-token platforms (`facebook`, `instagram`, `linkedin`, `pinterest`) append `connected`, `profileId`, `accountId`, `username` and, on API-key calls, `connect_token`. On failure the same error contract applies as on GET /v1/connect/{platform}: `error` and `platform` are always appended, other params are optional, and the value list there is not exhaustive. Note that on the tiktok, twitter and googleads flows `platform` carries the ads platform id (`tiktokads`, `xads`, `googleads`), not the value used in the request path. When omitted, the browser lands on the Zernio dashboard.
|
|
93
93
|
# @option opts [Boolean] :headless Enable headless mode (same-token platforms only)
|
|
94
94
|
# @option opts [Boolean] :force Force a fresh OAuth even when an account already exists. Normally the endpoint returns `alreadyConnected: true` whenever a connected account is found, keying off its active state rather than token liveness. Set `force=true` to bypass that and always receivean `authUrl`. Completing the returned OAuth refreshes the stored token on the existing posting and ads accounts in place.
|
|
95
95
|
# @option opts [String] :ad_account_id Scope ad sync to a single platform ad account. Without this param, sync covers every ad account the connected token can see. Supported on `facebook`/`instagram` (Meta, `act_<digits>`), `linkedin` (bare numeric sponsored-account id), `googleads` (bare customer id digits) and `twitter` (X Ads, base36 account id). `tiktok` scopes advertisers at OAuth and `pinterest` has no ads discovery, so both ignore it. Meta ids are additionally validated against the connected token; unreachable IDs return 400. Setting a scope also removes already synced ads from de-scoped ad accounts. For multiple accounts use `adAccountIds` instead.
|
|
@@ -204,7 +204,7 @@ describe 'ConnectApi' do
|
|
|
204
204
|
# @param platform Social media platform to connect
|
|
205
205
|
# @param profile_id Your Zernio profile ID (get from /v1/profiles). For WhatsApp, a Zernio-provisioned number can only be connected on the profile it was provisioned to; connecting from any other profile is rejected with a 409.
|
|
206
206
|
# @param [Hash] opts the optional parameters
|
|
207
|
-
# @option opts [String] :redirect_url Your custom redirect URL after connection completes. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. Result params are appended with the URL API, so an existing query string is preserved. Standard mode appends connected={platform}&profileId=X&accountId=Y&username=Z. Headless mode appends OAuth data params for platforms requiring selection (e.g. LinkedIn orgs, Facebook pages). If no selection is needed, the account is created directly and the redirect includes accountId.
|
|
207
|
+
# @option opts [String] :redirect_url Your custom redirect URL after connection completes. Accepts an http(s) URL, a custom app scheme for mobile deeplinks (e.g. myapp://callback), or a relative path. Result params are appended with the URL API, so an existing query string is preserved. Standard mode appends connected={platform}&profileId=X&accountId=Y&username=Z. Headless mode appends OAuth data params for platforms requiring selection (e.g. LinkedIn orgs, Facebook pages). If no selection is needed, the account is created directly and the redirect includes accountId. On failure, the browser is sent to the same redirect_url with `error` and `platform` appended. `error` and `platform` are always present. `error_message`, `is_user_fixable`, `reason` and `dashboard_url` are conditional and must be treated as optional. This list is NOT exhaustive and new values may be added at any time. Treat an unrecognized value as a generic failure rather than matching it exhaustively. Existing values are not renamed or removed without notice. OAuth and callback: oauth_denied, invalid_callback, invalid_state, unsupported_platform, connection_failed, internal_error, token_exchange_failed, byok_config_error, personal_account_not_supported, missing_google_permissions, platform_requires_destination, reconnect_account_mismatch, invalid_request Access and limits: profile_not_found, invalid_profile_id, access_denied, account_limit_exceeded, profile_limit_exceeded, payment_required Destination selection: no_facebook_pages, facebook_pages_error, no_google_locations, google_locations_error, google_permission_denied, no_snapchat_public_profiles, snapchat_profiles_error, discord_no_guild, slack_no_team WhatsApp: whatsapp_error, one_whatsapp_per_profile, whatsapp_number_already_connected, whatsapp_number_pinned_to_profile, connection_cancelled Google Ads (platform=googleads): google_ads_auth_failed, google_ads_invalid_state, google_ads_config_error, google_ads_token_failed, google_ads_quota_exhausted, google_ads_callback_error TikTok Ads (platform=tiktokads): tiktok_ads_auth_failed, tiktok_ads_invalid_state, tiktok_ads_access_denied, tiktok_ads_config_error, tiktok_ads_token_failed, tiktok_ads_account_not_found, tiktok_ads_callback_error X Ads (platform=xads): x_ads_denied, x_ads_auth_failed, x_ads_config_error, x_ads_account_not_found, x_ads_state_error, x_ads_token_failed, x_ads_token_missing, x_ads_callback_error Shopify (platform=shopify): shopify_auth_failed, shopify_config_error, shopify_invalid_state, shopify_invalid_hmac, shopify_invalid_shop, shopify_missing_scopes, shopify_callback_error 1. On this endpoint every upstream OAuth error is collapsed into `oauth_denied`. The provider's own value (for example Meta's `access_denied`) is not forwarded. The dedicated ads flows below are different: they use their own denial slugs and `google_ads_auth_failed` and `tiktok_ads_auth_failed` may carry the provider's raw error string in `error_message`. 2. On the tiktok and twitter ads flows `platform` carries the ads platform id (`tiktokads`, `xads`), not the value used in the request path. The googleads and shopify flows report `googleads` and `shopify`.
|
|
208
208
|
# @option opts [Boolean] :headless When true, the user is redirected to your redirect_url with raw OAuth data (code, state) instead of Zernio's default account selection UI. Use this to build a custom connect experience.
|
|
209
209
|
# @option opts [String] :login_method Instagram only. Which of the two Instagram connection methods to use. Ignored for every other platform. `instagram_login` (the default, and what you get if you omit this): the Instagram Login dialog. The user authorizes their Instagram professional account directly, no Facebook Page required. `facebook_login`: the Facebook Login dialog, i.e. \"Instagram API with Facebook Login\". The user authorizes a Facebook Page that has a linked Instagram professional account, and every API call for that account then runs through the Page. Use this when the customer manages Instagram through a Page and expects the Facebook consent screen. Because the user has to pick which Page to connect, the callback continues at the account-selection step, `/v1/connect/instagram/select-account`. `facebook_login` supports `headless=true` like the other selection platforms: the callback redirects to your `redirect_url` with `profileId`, `tempToken`, `platform=instagram`, `step=select_account` and `connect_token`, which you pass into the select-account endpoints to finish. The default `instagram_login` has no selection step, so it connects the account directly.
|
|
210
210
|
# @option opts [String] :onboarding WhatsApp only. Ignored for every other platform. Controls which screen Meta's Embedded Signup popup shows. If omitted, the connection defaults to coexistence (same as `business_app` below), preserving existing behavior for numbers already on the WhatsApp Business app. `api`: standard Embedded Signup, showing Meta's WABA/number picker. Use this to connect a phone number already on Cloud API elsewhere. `business_app`: coexistence, i.e. 'Connect existing WhatsApp Business app' (a number shared between Cloud API and the consumer WhatsApp Business app).
|
|
@@ -117,11 +117,11 @@ describe 'MessagesApi' do
|
|
|
117
117
|
|
|
118
118
|
# unit tests for get_message_attachment
|
|
119
119
|
# Resolve message attachment
|
|
120
|
-
# Resolve one attachment on a message to a media url that works right now. Instagram and Facebook sign DM media urls per request and expire them, so the `url` on a message is a snapshot: it works when you read the message and stops working later. This endpoint checks the stored url and, when it has gone stale, re-mints the message's media from Meta and persists it before answering. The message id never expires, so this URL is the one to store
|
|
120
|
+
# Resolve one attachment on a message to a media url that works right now. Instagram and Facebook sign DM media urls per request and expire them, so the `url` on a message is a snapshot: it works when you read the message and stops working later. This endpoint checks the stored url and, when it has gone stale, re-mints the message's media from Meta and persists it before answering. The message id never expires, so this URL is the one to store. It is returned ready-made on each attachment as `refreshUrl` when you read a message over REST. **Webhook payloads do not carry `refreshUrl`**, so a webhook-driven integration builds this URL itself. Every piece is in the event: `message.conversationId`, `message.platformMessageId`, the attachment's zero-based position, and `account.accountId`. Note that **`accountId` is a required query parameter**; omitting it returns `400` `missing_required_field`, which is the same requirement `GET /v1/whatsapp/media/{mediaId}` has. By default it responds `302` to the live media url, so it can be used directly as an `<img src>` on a browser session. API-key integrators should pass `?format=json` and read `url` off the body, since a browser cannot attach an Authorization header to an image request. Only Instagram and Facebook media can be re-minted. On other platforms the stored url is returned as-is when it still resolves, and `404` otherwise.
|
|
121
121
|
# @param conversation_id The conversation ID (Zernio id or platform conversation id)
|
|
122
122
|
# @param message_id The message id as returned by the list-messages endpoint (the platform message id)
|
|
123
123
|
# @param index Zero-based position of the attachment in the message's attachments array
|
|
124
|
-
# @param account_id Social account ID
|
|
124
|
+
# @param account_id Social account ID. Required: without it the request returns 400 missing_required_field.
|
|
125
125
|
# @param [Hash] opts the optional parameters
|
|
126
126
|
# @option opts [String] :format `redirect` (default) answers 302 to the media; `json` returns the url in the body
|
|
127
127
|
# @return [GetMessageAttachment200Response]
|
|
@@ -43,6 +43,12 @@ describe Zernio::GetInboxConversationMessages200ResponseMessagesInnerAttachments
|
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
+
describe 'test attribute "original_type"' 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
|
+
|
|
46
52
|
describe 'test attribute "url"' do
|
|
47
53
|
it 'should work' do
|
|
48
54
|
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
@@ -33,6 +33,12 @@ describe Zernio::WebhookPayloadMessageMessageAttachmentsInner do
|
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
describe 'test attribute "original_type"' 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
|
+
|
|
36
42
|
describe 'test attribute "url"' do
|
|
37
43
|
it 'should work' do
|
|
38
44
|
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
@@ -33,6 +33,12 @@ describe Zernio::WebhookPayloadMessageSentMessageAttachmentsInner do
|
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
describe 'test attribute "original_type"' 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
|
+
|
|
36
42
|
describe 'test attribute "url"' do
|
|
37
43
|
it 'should work' do
|
|
38
44
|
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|