unisender-ruby 0.1.1 → 0.2.0
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/CHANGELOG.md +89 -0
- data/CONTRIBUTING.md +10 -1
- data/README.md +55 -112
- data/docs/api.md +395 -210
- data/docs/execution.md +89 -0
- data/docs/import-recovery.md +41 -0
- data/docs/live-contracts.md +34 -0
- data/docs/migration-0.2.md +129 -0
- data/docs/rails.md +248 -0
- data/docs/releases.md +4 -4
- data/docs/testing.md +83 -0
- data/docs/usage.md +144 -0
- data/docs/webhooks.md +41 -0
- data/examples/campaign.rb +5 -6
- data/examples/campaign_lifecycle.rb +28 -0
- data/examples/check_connection.rb +1 -1
- data/examples/events.rb +1 -1
- data/examples/export.rb +20 -6
- data/examples/import.rb +3 -2
- data/examples/import_recovery.rb +70 -0
- data/examples/quickstart.rb +1 -1
- data/examples/subscribe.rb +2 -2
- data/lib/unisender/acceptance.rb +104 -0
- data/lib/unisender/attachment.rb +47 -0
- data/lib/unisender/batch_report.rb +115 -0
- data/lib/unisender/batch_summary.rb +87 -0
- data/lib/unisender/batches.rb +41 -12
- data/lib/unisender/campaign_workflow.rb +72 -0
- data/lib/unisender/client.rb +65 -33
- data/lib/unisender/client_configuration.rb +50 -0
- data/lib/unisender/client_execution.rb +43 -0
- data/lib/unisender/client_state.rb +31 -0
- data/lib/unisender/client_validation.rb +97 -0
- data/lib/unisender/configuration.rb +151 -0
- data/lib/unisender/contact_records.rb +251 -0
- data/lib/unisender/diagnostic_urls.rb +68 -0
- data/lib/unisender/diagnostics.rb +83 -0
- data/lib/unisender/download_target.rb +61 -0
- data/lib/unisender/download_transfer.rb +43 -0
- data/lib/unisender/downloader.rb +99 -0
- data/lib/unisender/error_diagnostics.rb +83 -0
- data/lib/unisender/errors.rb +125 -8
- data/lib/unisender/event_batches.rb +40 -0
- data/lib/unisender/event_payload.rb +50 -22
- data/lib/unisender/events.rb +21 -5
- data/lib/unisender/execution_context.rb +114 -0
- data/lib/unisender/form.rb +20 -12
- data/lib/unisender/helpers.rb +70 -10
- data/lib/unisender/hooks.rb +79 -0
- data/lib/unisender/import_cells.rb +62 -0
- data/lib/unisender/input_types.rb +30 -0
- data/lib/unisender/inputs.rb +262 -0
- data/lib/unisender/iteration.rb +15 -0
- data/lib/unisender/iterators.rb +60 -0
- data/lib/unisender/mail_inputs.rb +37 -0
- data/lib/unisender/named_inputs.rb +52 -0
- data/lib/unisender/observation.rb +30 -0
- data/lib/unisender/operation_contracts.rb +106 -0
- data/lib/unisender/operations/contacts_1.rb +4 -3
- data/lib/unisender/operations/contacts_2.rb +23 -4
- data/lib/unisender/operations/messages_1.rb +7 -4
- data/lib/unisender/operations/messages_2.rb +8 -3
- data/lib/unisender/operations/messages_3.rb +1 -1
- data/lib/unisender/operations/notes_1.rb +1 -1
- data/lib/unisender/operations/statistics_1.rb +3 -3
- data/lib/unisender/operations/templates_1.rb +2 -2
- data/lib/unisender/outcomes.rb +320 -0
- data/lib/unisender/page_response.rb +48 -0
- data/lib/unisender/paginated_operations.rb +43 -2
- data/lib/unisender/pagination.rb +53 -20
- data/lib/unisender/persistent_transport.rb +104 -0
- data/lib/unisender/rate_limiter.rb +72 -0
- data/lib/unisender/record.rb +210 -0
- data/lib/unisender/record_rows.rb +69 -0
- data/lib/unisender/records.rb +614 -0
- data/lib/unisender/request_execution.rb +108 -0
- data/lib/unisender/response.rb +13 -10
- data/lib/unisender/result_registry.rb +72 -0
- data/lib/unisender/results.rb +105 -0
- data/lib/unisender/retry_policy.rb +10 -16
- data/lib/unisender/serialization.rb +54 -0
- data/lib/unisender/statistic_records.rb +129 -0
- data/lib/unisender/task_response.rb +85 -0
- data/lib/unisender/task_waiter.rb +25 -11
- data/lib/unisender/testing/assertions.rb +48 -0
- data/lib/unisender/testing/fixtures.rb +24 -0
- data/lib/unisender/testing.rb +91 -0
- data/lib/unisender/transport.rb +17 -9
- data/lib/unisender/validation.rb +11 -9
- data/lib/unisender/version.rb +1 -1
- data/lib/unisender/webhooks/tokens.rb +38 -0
- data/lib/unisender/webhooks.rb +230 -0
- data/lib/unisender.rb +42 -0
- data/sig/acceptance.rbs +30 -0
- data/sig/attachment.rbs +15 -0
- data/sig/batch_summary.rbs +38 -0
- data/sig/campaign_workflow.rbs +20 -0
- data/sig/configuration.rbs +62 -0
- data/sig/connection_controls.rbs +55 -0
- data/sig/diagnostics.rbs +37 -0
- data/sig/domain_records.rbs +96 -0
- data/sig/downloads.rbs +53 -0
- data/sig/execution.rbs +52 -0
- data/sig/execution_context.rbs +46 -0
- data/sig/hooks.rbs +18 -0
- data/sig/inputs.rbs +84 -0
- data/sig/iterators.rbs +11 -0
- data/sig/mail_inputs.rbs +8 -0
- data/sig/manifest.yaml +11 -0
- data/sig/operation_contracts.rbs +28 -0
- data/sig/operations.rbs +73 -69
- data/sig/outcomes.rbs +90 -0
- data/sig/record.rbs +77 -0
- data/sig/records.rbs +182 -0
- data/sig/serialization.rbs +13 -0
- data/sig/tasks.rbs +26 -0
- data/sig/testing.rbs +54 -0
- data/sig/unisender.rbs +128 -39
- data/sig/webhooks.rbs +55 -0
- metadata +84 -3
data/docs/api.md
CHANGED
|
@@ -2,72 +2,143 @@
|
|
|
2
2
|
|
|
3
3
|
Contract audit: 2026-10-25. The [official UniSender documentation](https://www.unisender.com/ru/support/category/api/) is the source of truth. Tests use deterministic, artificial responses and do not establish live account compatibility.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Named HTTP operations return typed `Unisender::Response` subclasses. Required arguments are Ruby keywords. Optional keywords normally default to omission; documented client defaults take precedence. RBS signatures ship with the gem. Identifiers accept integers or strings; flags accept booleans or 0/1. Timestamp arguments accept strings or Ruby `Time` values. Time values use the method's documented UTC format.
|
|
6
6
|
|
|
7
7
|
Arrays supplied to comma-separated fields are joined only by named methods. For other array or hash arguments, the form encoder emits explicit bracket indices. `request(method, params: {})` accepts the exact wire method and parameters; it does not perform method-specific conversions or validation.
|
|
8
8
|
|
|
9
|
+
## Choose an operation
|
|
10
|
+
|
|
11
|
+
| Task | Starting point |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| Iterate lists | `get_lists.each` |
|
|
14
|
+
| Iterate every message or campaign | `each_message`, `each_message_summary`, or `each_campaign` |
|
|
15
|
+
| Manage a subscription | `subscribe(email:, list_ids:)` |
|
|
16
|
+
| Import application records | `import_contacts_in_batches(records:)` |
|
|
17
|
+
| Export contacts | `export_contacts(...).wait` |
|
|
18
|
+
| Inspect acceptance | `complete?`, `partial?`, `uncertain?`, and `failures` on report responses |
|
|
19
|
+
| Test without networking | [Testing transport](testing.md) |
|
|
20
|
+
| Configure an application | [Rails integration and configuration](rails.md) |
|
|
21
|
+
|
|
22
|
+
Named reads make one request. A fetched page's `each` remains local.
|
|
23
|
+
`each_page`, `auto_each`, and named iterators explicitly traverse further pages.
|
|
24
|
+
Batch commands execute immediately. Their `each_*` equivalents accept a block or return a lazy Enumerator.
|
|
25
|
+
|
|
26
|
+
### Effects and recovery
|
|
27
|
+
|
|
28
|
+
| Interface | Work performed | Recovery rule |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| `validate!`, record readers, serializers | Local only | Correct the reported input path. |
|
|
31
|
+
| Named reads | One HTTP request | Opt-in retries cover only the explicit read allowlist. |
|
|
32
|
+
| `each_*`, `each_page`, `auto_each` | Requests as consumed | Save `next_offset` after processing; repeated enumeration starts another sequence. |
|
|
33
|
+
| `subscribe`, create/update/delete operations | Account mutation | Reconcile an uncertain result before repeating. |
|
|
34
|
+
| `send_email`, `send_sms`, `send_test_email` | Sends messages | Acceptance does not prove delivery; never automatically replay. |
|
|
35
|
+
| `create_campaign`, `send_campaign` | Schedules or starts a send | Save the returned campaign ID and observe that same campaign. |
|
|
36
|
+
| Imports and Event Tracking | Mutations, possibly partial | Keep source IDs and checkpoints; [reconcile failed ranges](import-recovery.md). |
|
|
37
|
+
| `export_contacts`, report tasks | Starts a remote job | Save `task_uuid`; resume it with `get_task_result`. |
|
|
38
|
+
| `wait`, `download_to` | Explicit polling or download | Terminal waits are local; downloads retain confirmed partial bytes on failure. |
|
|
39
|
+
|
|
40
|
+
### Identifier map
|
|
41
|
+
|
|
42
|
+
| Identifier | Obtain from | Pass to |
|
|
43
|
+
| --- | --- | --- |
|
|
44
|
+
| List ID | `get_lists` record `id`, `create_list.id` | `list_id:` or `list_ids:` |
|
|
45
|
+
| Message ID | `create_email_message.message_id`, message record `id` | `get_message(id:)`, `send_test_email(id:)`, `create_campaign(message_id:)` |
|
|
46
|
+
| Campaign ID | `create_campaign.campaign_id` | `get_campaign_status(campaign_id:)`, campaign statistics |
|
|
47
|
+
| Accepted direct-email ID | `send_email.accepted_ids` | `check_email(email_id:)` |
|
|
48
|
+
| SMS ID | `send_sms` receipt `sms_id` | `check_sms(sms_id:)` |
|
|
49
|
+
| Template ID | Template record `id` | `get_template(template_id:)`, template update/delete |
|
|
50
|
+
| Task UUID | `export_contacts.task_uuid`, report task | `get_task_result(task_uuid:)` |
|
|
51
|
+
| Field, tag, or note ID | Corresponding record `id` | The operation's explicit `id:` or `field_ids:` keyword |
|
|
52
|
+
|
|
53
|
+
Identifiers refer to different resources even when their values happen to match.
|
|
54
|
+
`get_messages` returns detailed message records. `list_messages` returns message summaries.
|
|
55
|
+
Both fetch one page; use `each_message` or `each_message_summary` for explicit traversal.
|
|
56
|
+
|
|
57
|
+
### Common Ruby calls
|
|
58
|
+
|
|
59
|
+
Use these calls with an application-owned `client`. Mutations below change an account or send messages.
|
|
60
|
+
|
|
61
|
+
```ruby
|
|
62
|
+
client.get_lists.map(&:title)
|
|
63
|
+
client.get_contact(email: "person@example.test").email_address
|
|
64
|
+
client.validate!(:subscribe, email: "person@example.test", list_ids: [42])
|
|
65
|
+
client.subscribe(email: "person@example.test", list_ids: [42]) # Sends confirmation by default.
|
|
66
|
+
client.import_contacts(records: [{ email: "person@example.test" }]).complete?
|
|
67
|
+
client.send_sms(phone: ["79000000000"], sender: "Shop", text: "Hello").map(&:sms_id)
|
|
68
|
+
client.get_message(id: 12).subject
|
|
69
|
+
client.get_campaign_status(campaign_id: 34).status
|
|
70
|
+
client.get_task_result(task_uuid: "saved-task").wait
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
See the executable [campaign lifecycle](../examples/campaign_lifecycle.rb), [import recovery](import-recovery.md), and [export](../examples/export.rb) examples for multi-step workflows.
|
|
74
|
+
Object responses forward result readers and Hash-style lookups. Collections yield records and expose Array-style access.
|
|
75
|
+
Use `result` for the typed value, `data` for the raw envelope, and `http_status` for HTTP metadata.
|
|
76
|
+
|
|
9
77
|
## Implemented operations
|
|
10
78
|
|
|
11
79
|
The offline contract cases are in `test/fixtures/operations.json` and run through `test/operations_test.rb` in the source checkout. Every entry verifies the path, authentication body, required arguments, a successful result, and API failure propagation.
|
|
12
80
|
|
|
13
|
-
| Ruby method | Wire method and documentation | Required
|
|
14
|
-
| --- | --- | --- | --- |
|
|
15
|
-
| [`create_list`](#create_list) | [`createList`](https://www.unisender.com/ru/support/api/contacts/createlist/) | `title` | `before_subscribe_url`, `after_subscribe_url`, `sub_user_rights` |
|
|
16
|
-
| [`delete_list`](#delete_list) | [`deleteList`](https://www.unisender.com/ru/support/api/contacts/deletelist/) | `list_id` | None |
|
|
17
|
-
| [`exclude`](#exclude) | [`exclude`](https://www.unisender.com/ru/support/api/contacts/exclude/) | `
|
|
18
|
-
| [`export_contacts`](#export_contacts) | [`async/exportContacts`](https://www.unisender.com/ru/support/api/contacts/exportcontacts/) | None | `notify_url`, `list_id`, `field_names`, `email`, `phone`, `tag`, `email_status`, `phone_status`, `contact_status` |
|
|
19
|
-
| [`get_contact_count`](#get_contact_count) | [`getContactCount`](https://www.unisender.com/ru/support/api/contacts/getcontactcount/) | `list_id
|
|
20
|
-
| [`get_lists`](#get_lists) | [`getLists`](https://www.unisender.com/ru/support/api/contacts/getlists/) | None | None |
|
|
21
|
-
| [`get_total_contacts_count`](#get_total_contacts_count) | [`getTotalContactsCount`](https://www.unisender.com/ru/support/api/contacts/gettotalcontactscount/) | `login` | None |
|
|
22
|
-
| [`import_contacts`](#import_contacts) | [`importContacts`](https://www.unisender.com/ru/support/api/contacts/importcontacts/) | `field_names
|
|
23
|
-
| [`subscribe`](#subscribe) | [`subscribe`](https://www.unisender.com/ru/support/api/contacts/subscribe/) | `list_ids
|
|
24
|
-
| [`update_list`](#update_list) | [`updateList`](https://www.unisender.com/ru/support/api/contacts/updatelist/) | `list_id`, `title` | `before_subscribe_url`, `after_subscribe_url`, `sub_user_rights` |
|
|
25
|
-
| [`is_contact_in_lists`](#is_contact_in_lists) | [`isContactInLists`](https://www.unisender.com/ru/support/api/contacts/iscontactinlists/) | `email`, `list_ids`, `condition` | None |
|
|
26
|
-
| [`get_contact`](#get_contact) | [`getContact`](https://www.unisender.com/ru/support/api/contacts/getcontact/) | `email` | `include_lists`, `include_fields`, `include_details` |
|
|
27
|
-
| [`unsubscribe`](#unsubscribe) | [`unsubscribe`](https://www.unisender.com/ru/support/api/contacts/unsubscribe/) | `
|
|
28
|
-
| [`cancel_campaign`](#cancel_campaign) | [`cancelCampaign`](https://www.unisender.com/ru/support/api/messages/cancel-campaign/) | `campaign_id` | None |
|
|
29
|
-
| [`check_email`](#check_email) | [`checkEmail`](https://www.unisender.com/ru/support/api/messages/check-email/) | `email_id` | None |
|
|
30
|
-
| [`check_sms`](#check_sms) | [`checkSms`](https://www.unisender.com/ru/support/api/messages/check-sms/) | `sms_id` | None |
|
|
31
|
-
| [`create_campaign`](#create_campaign) | [`createCampaign`](https://www.unisender.com/ru/support/api/messages/createcampaign/) | `message_id` | `start_time`, `timezone`, `track_read`, `track_links`, `contacts`, `contacts_url`, `track_ga`, `payment_limit`, `payment_currency`, `ga_medium`, `ga_source`, `ga_campaign`, `ga_content`, `ga_term` |
|
|
32
|
-
| [`create_email_message`](#create_email_message) | [`createEmailMessage`](https://www.unisender.com/ru/support/api/messages/createemailmessage/) | `sender_name`, `sender_email`, `
|
|
33
|
-
| [`create_sms_message`](#create_sms_message) | [`createSmsMessage`](https://www.unisender.com/ru/support/api/messages/createsmsmessage/) | `sender`, `body`, `list_id` | `tag` |
|
|
34
|
-
| [`delete_message`](#delete_message) | [`deleteMessage`](https://www.unisender.com/ru/support/api/messages/deletemessage/) | `message_id` | None |
|
|
35
|
-
| [`get_actual_message_version`](#get_actual_message_version) | [`getActualMessageVersion`](https://www.unisender.com/ru/support/api/messages/get-actual-message-version/) | `message_id` | None |
|
|
36
|
-
| [`get_web_version`](#get_web_version) | [`getWebVersion`](https://www.unisender.com/ru/support/api/messages/getwebversion/) | `campaign_id` | None |
|
|
37
|
-
| [`send_email`](#send_email) | [`sendEmail`](https://www.unisender.com/ru/support/api/messages/sendemail/) | `email`, `
|
|
38
|
-
| [`send_sms`](#send_sms) | [`sendSms`](https://www.unisender.com/ru/support/api/messages/sendsms/) | `phone`, `sender`, `text` | None |
|
|
39
|
-
| [`send_test_email`](#send_test_email) | [`sendTestEmail`](https://www.unisender.com/ru/support/api/messages/sendtestemail/) | `email`, `id` | None |
|
|
40
|
-
| [`update_email_message`](#update_email_message) | [`updateEmailMessage`](https://www.unisender.com/ru/support/api/messages/updateemailmessage/) | `id` | `sender_name`, `sender_email`, `subject`, `body`, `list_id`, `text_body`, `lang`, `categories` |
|
|
41
|
-
| [`update_opt_in_email`](#update_opt_in_email) | [`updateOptInEmail`](https://www.unisender.com/ru/support/api/messages/updateoptinemail/) | `sender_name`, `sender_email`, `subject`, `body`, `list_id` | None |
|
|
42
|
-
| [`get_sender_domain_list`](#get_sender_domain_list) | [`getSenderDomainList`](https://www.unisender.com/ru/support/api/messages/getsenderdomainlist/) | `username` | `domain`, `limit`, `offset` |
|
|
43
|
-
| [`get_campaign_common_stats`](#get_campaign_common_stats) | [`getCampaignCommonStats`](https://www.unisender.com/ru/support/api/statistics/get-campaign-common-stats/) | `campaign_id` | None |
|
|
44
|
-
| [`get_campaign_delivery_stats`](#get_campaign_delivery_stats) | [`async/getCampaignDeliveryStats`](https://www.unisender.com/ru/support/api/statistics/getcampaigndeliverystats/) | `campaign_id` | `notify_url`, `changed_since`, `field_ids` |
|
|
45
|
-
| [`get_campaign_status`](#get_campaign_status) | [`getCampaignStatus`](https://www.unisender.com/ru/support/api/statistics/getcampaignstatus/) | `campaign_id` | None |
|
|
46
|
-
| [`get_messages`](#get_messages) | [`getMessages`](https://www.unisender.com/ru/support/api/statistics/getmessages/) | `date_from`, `date_to` | `limit`, `offset` |
|
|
47
|
-
| [`get_visited_links`](#get_visited_links) | [`getVisitedLinks`](https://www.unisender.com/ru/support/api/statistics/getvisitedlinks/) | `campaign_id` | `group` |
|
|
48
|
-
| [`list_messages`](#list_messages) | [`listMessages`](https://www.unisender.com/ru/support/api/statistics/listmessages/) | `date_from`, `date_to` | `limit`, `offset` |
|
|
49
|
-
| [`get_campaigns`](#get_campaigns) | [`getCampaigns`](https://www.unisender.com/ru/support/api/statistics/getcampaigns/) | `from` | `to`, `limit`, `offset` |
|
|
50
|
-
| [`get_message`](#get_message) | [`getMessage`](https://www.unisender.com/ru/support/api/statistics/getmessage/) | `id` | None |
|
|
51
|
-
| [`get_task_result`](#get_task_result) | [`async/getTaskResult`](https://www.unisender.com/ru/support/api/statistics/../contacts/exportcontacts/) | `task_uuid` | None |
|
|
52
|
-
| [`create_email_template`](#create_email_template) | [`createEmailTemplate`](https://www.unisender.com/ru/support/api/templates/createemailtemplate/) | `title`, `subject`, `body` | `description`, `text_body`, `lang` |
|
|
53
|
-
| [`delete_template`](#delete_template) | [`deleteTemplate`](https://www.unisender.com/ru/support/api/templates/deletetemplate/) | `template_id` | None |
|
|
54
|
-
| [`get_template`](#get_template) | [`getTemplate`](https://www.unisender.com/ru/support/api/templates/gettemplate/) |
|
|
55
|
-
| [`get_templates`](#get_templates) | [`getTemplates`](https://www.unisender.com/ru/support/api/templates/gettemplates/) | None | `type`, `date_from`, `date_to`, `limit`, `offset` |
|
|
56
|
-
| [`list_templates`](#list_templates) | [`listTemplates`](https://www.unisender.com/ru/support/api/templates/listtemplates/) | None | `type`, `date_from`, `date_to`, `limit`, `offset` |
|
|
57
|
-
| [`update_email_template`](#update_email_template) | [`updateEmailTemplate`](https://www.unisender.com/ru/support/api/templates/updateemailtemplate/) | `template_id` | `title`, `description`, `subject`, `body`, `text_body`, `lang` |
|
|
58
|
-
| [`create_field`](#create_field) | [`createField`](https://www.unisender.com/ru/support/api/inputs/createfield/) | `name`, `type` | `public_name` |
|
|
59
|
-
| [`delete_field`](#delete_field) | [`deleteField`](https://www.unisender.com/ru/support/api/inputs/deletefield/) | `id` | None |
|
|
60
|
-
| [`delete_tag`](#delete_tag) | [`deleteTag`](https://www.unisender.com/ru/support/api/inputs/deletetag/) | `id` | None |
|
|
61
|
-
| [`get_fields`](#get_fields) | [`getFields`](https://www.unisender.com/ru/support/api/inputs/getfields/) | None | None |
|
|
62
|
-
| [`get_tags`](#get_tags) | [`getTags`](https://www.unisender.com/ru/support/api/inputs/gettags/) | None | None |
|
|
63
|
-
| [`update_field`](#update_field) | [`updateField`](https://www.unisender.com/ru/support/api/inputs/updatefield/) | `id`, `name` | `public_name` |
|
|
64
|
-
| [`get_contact_field_values`](#get_contact_field_values) | [`getContactFieldValues`](https://www.unisender.com/ru/support/api/inputs/getcontactfieldvalues/) | `email`, `field_ids` | None |
|
|
65
|
-
| [`create_subscriber_note`](#create_subscriber_note) | [`createSubscriberNote`](https://www.unisender.com/ru/support/api/notes/createsubscibernote/) | `subscriber_id`, `content` | None |
|
|
66
|
-
| [`update_subscriber_note`](#update_subscriber_note) | [`updateSubscriberNote`](https://www.unisender.com/ru/support/api/notes/updatesubcribernote/) | `id`, `content` | None |
|
|
67
|
-
| [`delete_subscriber_note`](#delete_subscriber_note) | [`deleteSubscriberNote`](https://www.unisender.com/ru/support/api/notes/deletesubscribernote/) | `id` | None |
|
|
68
|
-
| [`get_subscriber_note`](#get_subscriber_note) | [`getSubscriberNote`](https://www.unisender.com/ru/support/api/notes/getsubscribernote/) | `id` | None |
|
|
69
|
-
| [`get_subscriber_notes`](#get_subscriber_notes) | [`getSubscriberNotes`](https://www.unisender.com/ru/support/api/notes/getsubscribernotes/) | `subscriber_id` | `limit`, `offset`, `order_type`, `order_by`, `is_pinned` |
|
|
70
|
-
| `
|
|
81
|
+
| Ruby method | Wire method and documentation | Required inputs | Optional keywords | Typed result |
|
|
82
|
+
| --- | --- | --- | --- | --- |
|
|
83
|
+
| [`create_list`](#create_list) | [`createList`](https://www.unisender.com/ru/support/api/contacts/createlist/) | `title` | `before_subscribe_url`, `after_subscribe_url`, `sub_user_rights` | `IdentifierRecordResponse` |
|
|
84
|
+
| [`delete_list`](#delete_list) | [`deleteList`](https://www.unisender.com/ru/support/api/contacts/deletelist/) | `list_id` | None | `ObjectResponse[Record]` |
|
|
85
|
+
| [`exclude`](#exclude) | [`exclude`](https://www.unisender.com/ru/support/api/contacts/exclude/) | `email` or `phone` with `list_ids`, or `contact_type` with `contact` | `contact_type`, `contact`, `email`, `phone`, `list_ids` | `ObjectResponse[Record]` |
|
|
86
|
+
| [`export_contacts`](#export_contacts) | [`async/exportContacts`](https://www.unisender.com/ru/support/api/contacts/exportcontacts/) | None | `notify_url`, `list_id`, `field_names`, `email`, `phone`, `tag`, `email_status`, `phone_status`, `contact_status` | `TaskResponse` |
|
|
87
|
+
| [`get_contact_count`](#get_contact_count) | [`getContactCount`](https://www.unisender.com/ru/support/api/contacts/getcontactcount/) | `list_id` and (`params` or explicit filters) | `params`, `tag_id`, `contact_type`, `search` | `ContactCountResponse` |
|
|
88
|
+
| [`get_lists`](#get_lists) | [`getLists`](https://www.unisender.com/ru/support/api/contacts/getlists/) | None | None | `CollectionResponse[List]` |
|
|
89
|
+
| [`get_total_contacts_count`](#get_total_contacts_count) | [`getTotalContactsCount`](https://www.unisender.com/ru/support/api/contacts/gettotalcontactscount/) | `login` | None | `TotalContactsResponse` |
|
|
90
|
+
| [`import_contacts`](#import_contacts) | [`importContacts`](https://www.unisender.com/ru/support/api/contacts/importcontacts/) | `records` or `field_names` with `data` | `field_names`, `data`, `records`, `overwrite_tags`, `overwrite_lists`, `telegram_bot_channel_id` | `ImportResponse` |
|
|
91
|
+
| [`subscribe`](#subscribe) | [`subscribe`](https://www.unisender.com/ru/support/api/contacts/subscribe/) | `list_ids` and (`email` or `fields`) | `fields`, `email`, `tags`, `double_optin`, `overwrite` | `SubscriptionResponse` |
|
|
92
|
+
| [`update_list`](#update_list) | [`updateList`](https://www.unisender.com/ru/support/api/contacts/updatelist/) | `list_id`, `title` | `before_subscribe_url`, `after_subscribe_url`, `sub_user_rights` | `ObjectResponse[Record]` |
|
|
93
|
+
| [`is_contact_in_lists`](#is_contact_in_lists) | [`isContactInLists`](https://www.unisender.com/ru/support/api/contacts/iscontactinlists/) | `email`, `list_ids`, `condition` | None | `Response[bool]` |
|
|
94
|
+
| [`get_contact`](#get_contact) | [`getContact`](https://www.unisender.com/ru/support/api/contacts/getcontact/) | `email` | `include_lists`, `include_fields`, `include_details` | `ContactResponse` |
|
|
95
|
+
| [`unsubscribe`](#unsubscribe) | [`unsubscribe`](https://www.unisender.com/ru/support/api/contacts/unsubscribe/) | `email` or `phone` with `list_ids`, or `contact_type` with `contact` | `contact_type`, `contact`, `email`, `phone`, `list_ids` | `ObjectResponse[Record]` |
|
|
96
|
+
| [`cancel_campaign`](#cancel_campaign) | [`cancelCampaign`](https://www.unisender.com/ru/support/api/messages/cancel-campaign/) | `campaign_id` | None | `ObjectResponse[Record]` |
|
|
97
|
+
| [`check_email`](#check_email) | [`checkEmail`](https://www.unisender.com/ru/support/api/messages/check-email/) | `email_id` | None | `CollectionResponse[EmailDelivery]` |
|
|
98
|
+
| [`check_sms`](#check_sms) | [`checkSms`](https://www.unisender.com/ru/support/api/messages/check-sms/) | `sms_id` | None | `StatusResponse` |
|
|
99
|
+
| [`create_campaign`](#create_campaign) | [`createCampaign`](https://www.unisender.com/ru/support/api/messages/createcampaign/) | `message_id` | `start_time`, `timezone`, `track_read`, `track_links`, `contacts`, `contacts_url`, `track_ga`, `payment_limit`, `payment_currency`, `ga_medium`, `ga_source`, `ga_campaign`, `ga_content`, `ga_term` | `CampaignCreatedResponse` |
|
|
100
|
+
| [`create_email_message`](#create_email_message) | [`createEmailMessage`](https://www.unisender.com/ru/support/api/messages/createemailmessage/) | `list_id`; sender defaults; content or a template | `sender_name`, `sender_email`, `subject`, `body`, `text_body`, `generate_text`, `tag`, `attachments`, `lang`, `template_id`, `system_template_id`, `wrap_type`, `categories` | `MessageCreatedResponse` |
|
|
101
|
+
| [`create_sms_message`](#create_sms_message) | [`createSmsMessage`](https://www.unisender.com/ru/support/api/messages/createsmsmessage/) | `sender`, `body`, `list_id` | `tag` | `MessageCreatedResponse` |
|
|
102
|
+
| [`delete_message`](#delete_message) | [`deleteMessage`](https://www.unisender.com/ru/support/api/messages/deletemessage/) | `message_id` | None | `ObjectResponse[Record]` |
|
|
103
|
+
| [`get_actual_message_version`](#get_actual_message_version) | [`getActualMessageVersion`](https://www.unisender.com/ru/support/api/messages/get-actual-message-version/) | `message_id` | None | `MessageVersionResponse` |
|
|
104
|
+
| [`get_web_version`](#get_web_version) | [`getWebVersion`](https://www.unisender.com/ru/support/api/messages/getwebversion/) | `campaign_id` | None | `WebVersionResponse` |
|
|
105
|
+
| [`send_email`](#send_email) | [`sendEmail`](https://www.unisender.com/ru/support/api/messages/sendemail/) | `email`, `subject`, `body`, `list_id`; sender defaults | `sender_name`, `sender_email`, `attachments`, `lang`, `track_read`, `track_links`, `cc`, `headers`, `images_as`, `ref_key`, `error_checking`, `metadata`, `reply_to`, `priority` | `SendResponse` |
|
|
106
|
+
| [`send_sms`](#send_sms) | [`sendSms`](https://www.unisender.com/ru/support/api/messages/sendsms/) | `phone`, `sender`, `text` | None | `CollectionResponse[SmsReceipt]` |
|
|
107
|
+
| [`send_test_email`](#send_test_email) | [`sendTestEmail`](https://www.unisender.com/ru/support/api/messages/sendtestemail/) | `email`, `id` | None | `MessageNoticeResponse` |
|
|
108
|
+
| [`update_email_message`](#update_email_message) | [`updateEmailMessage`](https://www.unisender.com/ru/support/api/messages/updateemailmessage/) | `id` | `sender_name`, `sender_email`, `subject`, `body`, `list_id`, `text_body`, `lang`, `categories` | `MessageCreatedResponse` |
|
|
109
|
+
| [`update_opt_in_email`](#update_opt_in_email) | [`updateOptInEmail`](https://www.unisender.com/ru/support/api/messages/updateoptinemail/) | `sender_name`, `sender_email`, `subject`, `body`, `list_id` | None | `ObjectResponse[Record]` |
|
|
110
|
+
| [`get_sender_domain_list`](#get_sender_domain_list) | [`getSenderDomainList`](https://www.unisender.com/ru/support/api/messages/getsenderdomainlist/) | `username` | `domain`, `limit`, `offset` | `PageResponse[SenderDomainGroup]` |
|
|
111
|
+
| [`get_campaign_common_stats`](#get_campaign_common_stats) | [`getCampaignCommonStats`](https://www.unisender.com/ru/support/api/statistics/get-campaign-common-stats/) | `campaign_id` | None | `CampaignStatsResponse` |
|
|
112
|
+
| [`get_campaign_delivery_stats`](#get_campaign_delivery_stats) | [`async/getCampaignDeliveryStats`](https://www.unisender.com/ru/support/api/statistics/getcampaigndeliverystats/) | `campaign_id` | `notify_url`, `changed_since`, `field_ids` | `TaskResponse` |
|
|
113
|
+
| [`get_campaign_status`](#get_campaign_status) | [`getCampaignStatus`](https://www.unisender.com/ru/support/api/statistics/getcampaignstatus/) | `campaign_id` | None | `StatusResponse` |
|
|
114
|
+
| [`get_messages`](#get_messages) | [`getMessages`](https://www.unisender.com/ru/support/api/statistics/getmessages/) | `date_from`, `date_to` | `limit`, `offset` | `PageResponse[Message]` |
|
|
115
|
+
| [`get_visited_links`](#get_visited_links) | [`getVisitedLinks`](https://www.unisender.com/ru/support/api/statistics/getvisitedlinks/) | `campaign_id` | `group` | `CollectionResponse[Record]` |
|
|
116
|
+
| [`list_messages`](#list_messages) | [`listMessages`](https://www.unisender.com/ru/support/api/statistics/listmessages/) | `date_from`, `date_to` | `limit`, `offset` | `PageResponse[Message]` |
|
|
117
|
+
| [`get_campaigns`](#get_campaigns) | [`getCampaigns`](https://www.unisender.com/ru/support/api/statistics/getcampaigns/) | `from` | `to`, `limit`, `offset` | `PageResponse[Campaign]` |
|
|
118
|
+
| [`get_message`](#get_message) | [`getMessage`](https://www.unisender.com/ru/support/api/statistics/getmessage/) | `id` | None | `MessageResponse` |
|
|
119
|
+
| [`get_task_result`](#get_task_result) | [`async/getTaskResult`](https://www.unisender.com/ru/support/api/statistics/../contacts/exportcontacts/) | `task_uuid` | None | `TaskResponse` |
|
|
120
|
+
| [`create_email_template`](#create_email_template) | [`createEmailTemplate`](https://www.unisender.com/ru/support/api/templates/createemailtemplate/) | `title`, `subject`, `body` | `description`, `text_body`, `lang` | `IdentifierRecordResponse` |
|
|
121
|
+
| [`delete_template`](#delete_template) | [`deleteTemplate`](https://www.unisender.com/ru/support/api/templates/deletetemplate/) | `template_id` | None | `ObjectResponse[Record]` |
|
|
122
|
+
| [`get_template`](#get_template) | [`getTemplate`](https://www.unisender.com/ru/support/api/templates/gettemplate/) | `template_id` or `system_template_id` | `template_id`, `system_template_id` | `TemplateResponse` |
|
|
123
|
+
| [`get_templates`](#get_templates) | [`getTemplates`](https://www.unisender.com/ru/support/api/templates/gettemplates/) | None | `type`, `date_from`, `date_to`, `limit`, `offset` | `PageResponse[Template]` |
|
|
124
|
+
| [`list_templates`](#list_templates) | [`listTemplates`](https://www.unisender.com/ru/support/api/templates/listtemplates/) | None | `type`, `date_from`, `date_to`, `limit`, `offset` | `PageResponse[Template]` |
|
|
125
|
+
| [`update_email_template`](#update_email_template) | [`updateEmailTemplate`](https://www.unisender.com/ru/support/api/templates/updateemailtemplate/) | `template_id` | `title`, `description`, `subject`, `body`, `text_body`, `lang` | `IdentifierRecordResponse` |
|
|
126
|
+
| [`create_field`](#create_field) | [`createField`](https://www.unisender.com/ru/support/api/inputs/createfield/) | `name`, `type` | `public_name` | `IdentifierRecordResponse` |
|
|
127
|
+
| [`delete_field`](#delete_field) | [`deleteField`](https://www.unisender.com/ru/support/api/inputs/deletefield/) | `id` | None | `ObjectResponse[Record]` |
|
|
128
|
+
| [`delete_tag`](#delete_tag) | [`deleteTag`](https://www.unisender.com/ru/support/api/inputs/deletetag/) | `id` | None | `ObjectResponse[Record]` |
|
|
129
|
+
| [`get_fields`](#get_fields) | [`getFields`](https://www.unisender.com/ru/support/api/inputs/getfields/) | None | None | `CollectionResponse[Field]` |
|
|
130
|
+
| [`get_tags`](#get_tags) | [`getTags`](https://www.unisender.com/ru/support/api/inputs/gettags/) | None | None | `CollectionResponse[Tag]` |
|
|
131
|
+
| [`update_field`](#update_field) | [`updateField`](https://www.unisender.com/ru/support/api/inputs/updatefield/) | `id`, `name` | `public_name` | `OptionalIdentifierResponse` |
|
|
132
|
+
| [`get_contact_field_values`](#get_contact_field_values) | [`getContactFieldValues`](https://www.unisender.com/ru/support/api/inputs/getcontactfieldvalues/) | `email`, `field_ids` | None | `ContactFieldsResponse` |
|
|
133
|
+
| [`create_subscriber_note`](#create_subscriber_note) | [`createSubscriberNote`](https://www.unisender.com/ru/support/api/notes/createsubscibernote/) | `subscriber_id`, `content` | None | `IdentifierRecordResponse` |
|
|
134
|
+
| [`update_subscriber_note`](#update_subscriber_note) | [`updateSubscriberNote`](https://www.unisender.com/ru/support/api/notes/updatesubcribernote/) | `id`, `content` | None | `IdentifierRecordResponse` |
|
|
135
|
+
| [`delete_subscriber_note`](#delete_subscriber_note) | [`deleteSubscriberNote`](https://www.unisender.com/ru/support/api/notes/deletesubscribernote/) | `id` | None | `ObjectResponse[Record]` |
|
|
136
|
+
| [`get_subscriber_note`](#get_subscriber_note) | [`getSubscriberNote`](https://www.unisender.com/ru/support/api/notes/getsubscribernote/) | `id` | None | `NoteResponse` |
|
|
137
|
+
| [`get_subscriber_notes`](#get_subscriber_notes) | [`getSubscriberNotes`](https://www.unisender.com/ru/support/api/notes/getsubscribernotes/) | `subscriber_id` | `limit`, `offset`, `order_type`, `order_by`, `is_pinned` | `PageResponse[Note]` |
|
|
138
|
+
| [`set_hook`](#set_hook) | [`setHook`](https://www.unisender.com/ru/support/api/common/sistema-uvedomlenij-o-sobytiyah-webhooks/) | `hook_url`, `events` | `event_format`, `max_parallel`, `single_event`, `status` | `Response[json]` |
|
|
139
|
+
| [`list_hooks`](#list_hooks) | [`listHooks`](https://www.unisender.com/ru/support/api/common/sistema-uvedomlenij-o-sobytiyah-webhooks/) | None | None | `CollectionResponse[Hook]` |
|
|
140
|
+
| [`remove_hook`](#remove_hook) | [`removeHook`](https://www.unisender.com/ru/support/api/common/sistema-uvedomlenij-o-sobytiyah-webhooks/) | `hook_url` | None | `Response[json]` |
|
|
141
|
+
| `track_events` | [Event Tracking](https://www.unisender.com/ru/support/api/event-tracking-api/) | `events` | None | `EventResponse` |
|
|
71
142
|
|
|
72
143
|
## Reading the contracts
|
|
73
144
|
|
|
@@ -75,7 +146,7 @@ Expand an operation below for its accepted Ruby types and result shape. `id` mea
|
|
|
75
146
|
|
|
76
147
|
Named methods accept Arrays for the documented comma-separated fields and join them before encoding. Other nested arrays and hashes retain bracket indices. An empty String/Array/Hash is rejected for a required value. Method-specific constraints beyond the structural checks are validated by the service; refer to the linked official page for account permissions, current limits, and additional response fields.
|
|
77
148
|
|
|
78
|
-
|
|
149
|
+
Named-operation results are immutable typed records or collections. The wire shapes below describe `response.data`; records expose documented fields and string-key lookup. HTTP metadata uses `response.http_status`. See [the migration guide](migration-0.2.md). Unknown fields remain in `response.data`, even when a result type lists only its guaranteed fields. API errors raise `APIError`, HTTP errors raise `HTTPError`, malformed successful responses raise `InvalidResponseError`, and connection failures raise `TransportError`; none should be interpreted as an empty success. Import and send operations can also return per-record failures inside a successful result.
|
|
79
150
|
|
|
80
151
|
## Operation contracts
|
|
81
152
|
|
|
@@ -88,9 +159,9 @@ All result descriptions refer to `response.result`, not the enclosing response.
|
|
|
88
159
|
| Keyword | Ruby type | Presence |
|
|
89
160
|
| --- | --- | --- |
|
|
90
161
|
| `title` | `String` | Required |
|
|
91
|
-
| `before_subscribe_url` | `String` | Optional, omitted |
|
|
92
|
-
| `after_subscribe_url` | `String` | Optional, omitted |
|
|
93
|
-
| `sub_user_rights` | `params` | Optional, omitted |
|
|
162
|
+
| `before_subscribe_url` | `String \| nil` | Optional, omitted |
|
|
163
|
+
| `after_subscribe_url` | `String \| nil` | Optional, omitted |
|
|
164
|
+
| `sub_user_rights` | `params \| nil` | Optional, omitted |
|
|
94
165
|
|
|
95
166
|
**Result:** Object with `id`, the new list identifier.
|
|
96
167
|
|
|
@@ -108,7 +179,7 @@ The title must be unique within the account. `sub_user_rights` maps user IDs to
|
|
|
108
179
|
| --- | --- | --- |
|
|
109
180
|
| `list_id` | `id` | Required |
|
|
110
181
|
|
|
111
|
-
**Result:** Empty JSON result on success.
|
|
182
|
+
**Result:** Empty JSON result on success. An empty legacy array is normalized to an empty record; `data` retains the original shape. Deletes the list; review the upstream consequences before use.
|
|
112
183
|
|
|
113
184
|
</details>
|
|
114
185
|
|
|
@@ -120,11 +191,13 @@ The title must be unique within the account. `sub_user_rights` maps user IDs to
|
|
|
120
191
|
|
|
121
192
|
| Keyword | Ruby type | Presence |
|
|
122
193
|
| --- | --- | --- |
|
|
123
|
-
| `contact_type` | `
|
|
124
|
-
| `contact` | `String
|
|
125
|
-
| `
|
|
194
|
+
| `contact_type` | `contact_type?` | Required with contact |
|
|
195
|
+
| `contact` | `String?` | Required with contact_type |
|
|
196
|
+
| `email` | `String?` | Alternative contact selector; requires list_ids |
|
|
197
|
+
| `phone` | `String?` | Alternative contact selector; requires list_ids |
|
|
198
|
+
| `list_ids` | `String \| Array[id] \| nil` | Optional, omitted |
|
|
126
199
|
|
|
127
|
-
**Result:** Empty JSON result on success.
|
|
200
|
+
**Result:** Empty JSON result on success. Named calls normalize an empty legacy array to an empty record; `data` retains the wire shape. Removes membership in the selected lists.
|
|
128
201
|
|
|
129
202
|
`contact_type` is `"email"` or `"phone"`. Omitted `list_ids` applies the upstream account-wide behavior; provide explicit IDs when intending to affect selected lists only.
|
|
130
203
|
|
|
@@ -138,15 +211,15 @@ The title must be unique within the account. `sub_user_rights` maps user IDs to
|
|
|
138
211
|
|
|
139
212
|
| Keyword | Ruby type | Presence |
|
|
140
213
|
| --- | --- | --- |
|
|
141
|
-
| `notify_url` | `String` | Optional, omitted |
|
|
142
|
-
| `list_id` | `id` | Optional, omitted |
|
|
143
|
-
| `field_names` | `Array[String]` | Optional, omitted |
|
|
144
|
-
| `email` | `String` | Optional, omitted |
|
|
145
|
-
| `phone` | `String` | Optional, omitted |
|
|
146
|
-
| `tag` | `String` | Optional, omitted |
|
|
147
|
-
| `email_status` | `String` | Optional, omitted |
|
|
148
|
-
| `phone_status` | `String` | Optional, omitted |
|
|
149
|
-
| `contact_status` | `String` | Optional, omitted |
|
|
214
|
+
| `notify_url` | `String \| nil` | Optional, omitted |
|
|
215
|
+
| `list_id` | `id \| nil` | Optional, omitted |
|
|
216
|
+
| `field_names` | `Array[String] \| nil` | Optional, omitted |
|
|
217
|
+
| `email` | `String \| nil` | Optional, omitted |
|
|
218
|
+
| `phone` | `String \| nil` | Optional, omitted |
|
|
219
|
+
| `tag` | `String \| nil` | Optional, omitted |
|
|
220
|
+
| `email_status` | `String \| nil` | Optional, omitted |
|
|
221
|
+
| `phone_status` | `String \| nil` | Optional, omitted |
|
|
222
|
+
| `contact_status` | `String \| nil` | Optional, omitted |
|
|
150
223
|
|
|
151
224
|
**Result:** Object with `task_uuid` and initial `status`. Poll `get_task_result`, or use `wait_for_task`; a completed job provides `file_to_download`.
|
|
152
225
|
|
|
@@ -161,9 +234,12 @@ The title must be unique within the account. `sub_user_rights` maps user IDs to
|
|
|
161
234
|
| Keyword | Ruby type | Presence |
|
|
162
235
|
| --- | --- | --- |
|
|
163
236
|
| `list_id` | `id` | Required |
|
|
164
|
-
| `params` | `params
|
|
237
|
+
| `params` | `params?` | Alternative to explicit filters |
|
|
238
|
+
| `tag_id` | `id?` | Optional, omitted |
|
|
239
|
+
| `contact_type` | `contact_type \| "address" \| nil` | Required when search is supplied |
|
|
240
|
+
| `search` | `String?` | Optional, omitted |
|
|
165
241
|
|
|
166
|
-
**
|
|
242
|
+
**Wire result:** Object with `listId`, `searchParams`, and a String `count`. The typed `response.count` reader returns an Integer.
|
|
167
243
|
|
|
168
244
|
`params` must contain at least one filter. Use `tagId`, `type` (`"address"` or `"phone"`), and optionally `search`; `search` requires `type`.
|
|
169
245
|
|
|
@@ -203,15 +279,16 @@ No operation arguments.
|
|
|
203
279
|
|
|
204
280
|
| Keyword | Ruby type | Presence |
|
|
205
281
|
| --- | --- | --- |
|
|
206
|
-
| `field_names` | `Array[String]
|
|
207
|
-
| `data` | `Array[Array[parameter]]
|
|
208
|
-
| `
|
|
209
|
-
| `
|
|
210
|
-
| `
|
|
282
|
+
| `field_names` | `Array[String]?` | Required with data |
|
|
283
|
+
| `data` | `Array[Array[parameter]]?` | Required with field_names |
|
|
284
|
+
| `records` | `Enumerable[params]?` | Alternative to field_names and data |
|
|
285
|
+
| `overwrite_tags` | `flag \| nil` | Optional, omitted |
|
|
286
|
+
| `overwrite_lists` | `flag \| nil` | Optional, omitted |
|
|
287
|
+
| `telegram_bot_channel_id` | `String \| nil` | Optional, omitted |
|
|
211
288
|
|
|
212
289
|
**Result:** Object with Integer counters `total`, `inserted`, `updated`, `deleted`, `new_emails`, and `invalid`; `log` contains per-row `index`, `code`, and `message`. A successful response can include rejected rows. Inspect `invalid` and `log`.
|
|
213
290
|
|
|
214
|
-
`field_names` must be unique and include `"email"`. Supply 1 to 500 rows with exactly one cell per column. `overwrite_tags` and `overwrite_lists` default to 0; setting them to 1 replaces existing associations. `email_list_ids` is a comma-separated cell, not an Array. `telegram_bot_channel_id` is required upstream when a row contains `telegram_user_id`.
|
|
291
|
+
`records:` is mutually exclusive with `field_names:` and `data:`. Record keys must be consistent and include email; the first record determines column order. Arrays validate before sending, while streams validate as consumed. `field_names` must be unique and include `"email"`. Supply 1 to 500 rows with exactly one cell per column. `overwrite_tags` and `overwrite_lists` default to 0; setting them to 1 replaces existing associations. `email_list_ids` is a comma-separated cell, not an Array. `telegram_bot_channel_id` is required upstream when a row contains `telegram_user_id`.
|
|
215
292
|
|
|
216
293
|
</details>
|
|
217
294
|
|
|
@@ -224,14 +301,15 @@ No operation arguments.
|
|
|
224
301
|
| Keyword | Ruby type | Presence |
|
|
225
302
|
| --- | --- | --- |
|
|
226
303
|
| `list_ids` | `String \| Array[id]` | Required |
|
|
227
|
-
| `fields` | `params
|
|
228
|
-
| `
|
|
229
|
-
| `
|
|
230
|
-
| `
|
|
304
|
+
| `fields` | `params?` | Required unless email is supplied |
|
|
305
|
+
| `email` | `String?` | Required unless supplied in fields |
|
|
306
|
+
| `tags` | `String \| Array[id] \| nil` | Optional, omitted |
|
|
307
|
+
| `double_optin` | `Integer \| :request_confirmation \| :already_confirmed \| :confirm_if_needed \| nil` | Optional, omitted |
|
|
308
|
+
| `overwrite` | `Integer \| :preserve \| :replace \| :update \| nil` | Optional, omitted |
|
|
231
309
|
|
|
232
310
|
**Result:** Object with `person_id`, the contact identifier. Success does not mean the contact has confirmed subscription.
|
|
233
311
|
|
|
234
|
-
`
|
|
312
|
+
Supply `email:` directly or include email in `fields:`; custom names are case-sensitive. Conflicting email values raise before sending. Named consent modes are `:request_confirmation` (0), `:already_confirmed` (3), and `:confirm_if_needed` (4). Named overwrite modes are `:preserve` (0), `:replace` (1), and `:update` (2). `double_optin` accepts 0 (confirmation email), 3 (prior consent, no confirmation email), or 4 (reuse an already-confirmed contact, otherwise send confirmation). `overwrite` accepts 0 (preserve existing), 1 (replace fields, tags, and list membership), or 2 (update supplied fields). Up to ten tags are allowed.
|
|
235
313
|
|
|
236
314
|
</details>
|
|
237
315
|
|
|
@@ -245,11 +323,11 @@ No operation arguments.
|
|
|
245
323
|
| --- | --- | --- |
|
|
246
324
|
| `list_id` | `id` | Required |
|
|
247
325
|
| `title` | `String` | Required |
|
|
248
|
-
| `before_subscribe_url` | `String` | Optional, omitted |
|
|
249
|
-
| `after_subscribe_url` | `String` | Optional, omitted |
|
|
250
|
-
| `sub_user_rights` | `params` | Optional, omitted |
|
|
326
|
+
| `before_subscribe_url` | `String \| nil` | Optional, omitted |
|
|
327
|
+
| `after_subscribe_url` | `String \| nil` | Optional, omitted |
|
|
328
|
+
| `sub_user_rights` | `params \| nil` | Optional, omitted |
|
|
251
329
|
|
|
252
|
-
**Result:** Empty JSON result on success.
|
|
330
|
+
**Result:** Empty JSON result on success. Named calls normalize an empty legacy array to an empty record; `data` retains the wire shape.
|
|
253
331
|
|
|
254
332
|
</details>
|
|
255
333
|
|
|
@@ -280,9 +358,9 @@ No operation arguments.
|
|
|
280
358
|
| Keyword | Ruby type | Presence |
|
|
281
359
|
| --- | --- | --- |
|
|
282
360
|
| `email` | `String` | Required |
|
|
283
|
-
| `include_lists` | `flag` | Optional, omitted |
|
|
284
|
-
| `include_fields` | `flag` | Optional, omitted |
|
|
285
|
-
| `include_details` | `flag` | Optional, omitted |
|
|
361
|
+
| `include_lists` | `flag \| nil` | Optional, omitted |
|
|
362
|
+
| `include_fields` | `flag \| nil` | Optional, omitted |
|
|
363
|
+
| `include_details` | `flag \| nil` | Optional, omitted |
|
|
286
364
|
|
|
287
365
|
**Result:** Object with nested `email` contact details. `phone`, `lists`, and custom `fields` depend on the contact and include options. Access the address as `result.fetch("email").fetch("email")`, not `result.fetch("email")` alone.
|
|
288
366
|
|
|
@@ -296,11 +374,13 @@ No operation arguments.
|
|
|
296
374
|
|
|
297
375
|
| Keyword | Ruby type | Presence |
|
|
298
376
|
| --- | --- | --- |
|
|
299
|
-
| `contact_type` | `
|
|
300
|
-
| `contact` | `String
|
|
301
|
-
| `
|
|
377
|
+
| `contact_type` | `contact_type?` | Required with contact |
|
|
378
|
+
| `contact` | `String?` | Required with contact_type |
|
|
379
|
+
| `email` | `String?` | Alternative contact selector; requires list_ids |
|
|
380
|
+
| `phone` | `String?` | Alternative contact selector; requires list_ids |
|
|
381
|
+
| `list_ids` | `String \| Array[id] \| nil` | Optional, omitted |
|
|
302
382
|
|
|
303
|
-
**Result:** Empty JSON result on success.
|
|
383
|
+
**Result:** Empty JSON result on success. Named calls normalize an empty legacy array to an empty record; `data` retains the wire shape. Unsubscribes the specified contact from the selected lists.
|
|
304
384
|
|
|
305
385
|
`contact_type` is `"email"` or `"phone"`. Omitted `list_ids` applies the upstream account-wide behavior; provide explicit IDs when intending to affect selected lists only.
|
|
306
386
|
|
|
@@ -357,20 +437,20 @@ No operation arguments.
|
|
|
357
437
|
| Keyword | Ruby type | Presence |
|
|
358
438
|
| --- | --- | --- |
|
|
359
439
|
| `message_id` | `id` | Required |
|
|
360
|
-
| `start_time` | `String` | Optional, omitted |
|
|
361
|
-
| `timezone` | `String` | Optional, omitted |
|
|
362
|
-
| `track_read` | `flag` | Optional, omitted |
|
|
363
|
-
| `track_links` | `flag` | Optional, omitted |
|
|
364
|
-
| `contacts` | `String \| Array[id]` | Optional, omitted |
|
|
365
|
-
| `contacts_url` | `String` | Optional, omitted |
|
|
366
|
-
| `track_ga` | `flag` | Optional, omitted |
|
|
367
|
-
| `payment_limit` | `Integer \| Float` | Optional, omitted |
|
|
368
|
-
| `payment_currency` | `String` | Optional, omitted |
|
|
369
|
-
| `ga_medium` | `String` | Optional, omitted |
|
|
370
|
-
| `ga_source` | `String` | Optional, omitted |
|
|
371
|
-
| `ga_campaign` | `String` | Optional, omitted |
|
|
372
|
-
| `ga_content` | `String` | Optional, omitted |
|
|
373
|
-
| `ga_term` | `String` | Optional, omitted |
|
|
440
|
+
| `start_time` | `String \| Time \| nil` | Optional, omitted |
|
|
441
|
+
| `timezone` | `String \| nil` | Optional, omitted |
|
|
442
|
+
| `track_read` | `flag \| nil` | Optional, omitted |
|
|
443
|
+
| `track_links` | `flag \| nil` | Optional, omitted |
|
|
444
|
+
| `contacts` | `String \| Array[id] \| nil` | Optional, omitted |
|
|
445
|
+
| `contacts_url` | `String \| nil` | Optional, omitted |
|
|
446
|
+
| `track_ga` | `flag \| nil` | Optional, omitted |
|
|
447
|
+
| `payment_limit` | `Integer \| Float \| nil` | Optional, omitted |
|
|
448
|
+
| `payment_currency` | `String \| nil` | Optional, omitted |
|
|
449
|
+
| `ga_medium` | `String \| nil` | Optional, omitted |
|
|
450
|
+
| `ga_source` | `String \| nil` | Optional, omitted |
|
|
451
|
+
| `ga_campaign` | `String \| nil` | Optional, omitted |
|
|
452
|
+
| `ga_content` | `String \| nil` | Optional, omitted |
|
|
453
|
+
| `ga_term` | `String \| nil` | Optional, omitted |
|
|
374
454
|
|
|
375
455
|
**Result:** Object with `campaign_id` and String `status`, such as `scheduled` or `waits_censor`. `count` is deprecated and documented as zero. Accepted does not mean delivered.
|
|
376
456
|
|
|
@@ -386,20 +466,20 @@ No operation arguments.
|
|
|
386
466
|
|
|
387
467
|
| Keyword | Ruby type | Presence |
|
|
388
468
|
| --- | --- | --- |
|
|
389
|
-
| `sender_name` | `String` | Required |
|
|
390
|
-
| `sender_email` | `String` | Required |
|
|
391
469
|
| `list_id` | `id` | Required |
|
|
392
|
-
| `
|
|
393
|
-
| `
|
|
394
|
-
| `
|
|
395
|
-
| `
|
|
396
|
-
| `
|
|
397
|
-
| `
|
|
398
|
-
| `
|
|
399
|
-
| `
|
|
400
|
-
| `
|
|
401
|
-
| `
|
|
402
|
-
| `
|
|
470
|
+
| `sender_name` | `String?` | Required unless configured as a default |
|
|
471
|
+
| `sender_email` | `String?` | Required unless configured as a default |
|
|
472
|
+
| `subject` | `String \| nil` | Required without a template |
|
|
473
|
+
| `body` | `String \| nil` | Required without a template |
|
|
474
|
+
| `text_body` | `String \| nil` | Optional, omitted |
|
|
475
|
+
| `generate_text` | `flag \| nil` | Optional, omitted |
|
|
476
|
+
| `tag` | `String \| nil` | Optional, omitted |
|
|
477
|
+
| `attachments` | `Hash[String, String] \| Attachment \| Array[Attachment] \| nil` | Optional, omitted |
|
|
478
|
+
| `lang` | `String \| nil` | Optional, omitted |
|
|
479
|
+
| `template_id` | `id \| nil` | Optional, omitted |
|
|
480
|
+
| `system_template_id` | `id \| nil` | Optional, omitted |
|
|
481
|
+
| `wrap_type` | `String \| nil` | Optional, omitted |
|
|
482
|
+
| `categories` | `String \| Array[id] \| nil` | Optional, omitted |
|
|
403
483
|
|
|
404
484
|
**Result:** Object with `message_id`. Creates a message without sending it. Pass the identifier to `create_campaign` to send.
|
|
405
485
|
|
|
@@ -418,7 +498,7 @@ Supply nonempty `subject` and `body`, or select `template_id` / `system_template
|
|
|
418
498
|
| `sender` | `String` | Required |
|
|
419
499
|
| `body` | `String` | Required |
|
|
420
500
|
| `list_id` | `id` | Required |
|
|
421
|
-
| `tag` | `String` | Optional, omitted |
|
|
501
|
+
| `tag` | `String \| nil` | Optional, omitted |
|
|
422
502
|
|
|
423
503
|
**Result:** Object with `message_id`. Creates a message without sending it.
|
|
424
504
|
|
|
@@ -434,7 +514,7 @@ Supply nonempty `subject` and `body`, or select `template_id` / `system_template
|
|
|
434
514
|
| --- | --- | --- |
|
|
435
515
|
| `message_id` | `id` | Required |
|
|
436
516
|
|
|
437
|
-
**Result:** Empty JSON result on success.
|
|
517
|
+
**Result:** Empty JSON result on success. Named calls normalize an empty legacy array to an empty record; `data` retains the wire shape.
|
|
438
518
|
|
|
439
519
|
</details>
|
|
440
520
|
|
|
@@ -475,21 +555,23 @@ Supply nonempty `subject` and `body`, or select `template_id` / `system_template
|
|
|
475
555
|
| Keyword | Ruby type | Presence |
|
|
476
556
|
| --- | --- | --- |
|
|
477
557
|
| `email` | `String` | Required |
|
|
478
|
-
| `sender_name` | `String` | Required |
|
|
479
|
-
| `sender_email` | `String` | Required |
|
|
480
558
|
| `subject` | `String` | Required |
|
|
481
559
|
| `body` | `String` | Required |
|
|
482
560
|
| `list_id` | `id` | Required |
|
|
483
|
-
| `
|
|
484
|
-
| `
|
|
485
|
-
| `
|
|
486
|
-
| `
|
|
487
|
-
| `
|
|
488
|
-
| `
|
|
489
|
-
| `
|
|
490
|
-
| `
|
|
491
|
-
| `
|
|
492
|
-
| `
|
|
561
|
+
| `sender_name` | `String?` | Required unless configured as a default |
|
|
562
|
+
| `sender_email` | `String?` | Required unless configured as a default |
|
|
563
|
+
| `attachments` | `Hash[String, String] \| Attachment \| Array[Attachment] \| nil` | Optional, omitted |
|
|
564
|
+
| `lang` | `String \| nil` | Optional, omitted |
|
|
565
|
+
| `track_read` | `flag \| nil` | Optional, omitted |
|
|
566
|
+
| `track_links` | `flag \| nil` | Optional, omitted |
|
|
567
|
+
| `cc` | `String \| nil` | Optional, omitted |
|
|
568
|
+
| `headers` | `String \| params \| nil` | Optional, omitted |
|
|
569
|
+
| `images_as` | `String \| Symbol \| nil` | Optional, omitted |
|
|
570
|
+
| `ref_key` | `String \| nil` | Optional, omitted |
|
|
571
|
+
| `error_checking` | `flag \| nil` | Optional, defaults to true; nil omits the field |
|
|
572
|
+
| `metadata` | `params \| nil` | Optional, omitted |
|
|
573
|
+
| `reply_to` | `String \| nil` | Optional, omitted |
|
|
574
|
+
| `priority` | `String \| nil` | Optional, omitted |
|
|
493
575
|
|
|
494
576
|
**Result:** With `error_checking: 1` or `cc`, an Array of per-recipient results containing `index`, `email`, and accepted message `id`. Without either, the legacy result is an Object with `email_id`. With `error_checking: 1`, also inspect recipient `errors`; the top-level success envelope alone is insufficient.
|
|
495
577
|
|
|
@@ -505,7 +587,7 @@ Use a verified sender and consenting recipients. `attachments` maps filenames to
|
|
|
505
587
|
|
|
506
588
|
| Keyword | Ruby type | Presence |
|
|
507
589
|
| --- | --- | --- |
|
|
508
|
-
| `phone` | `String` | Required |
|
|
590
|
+
| `phone` | `String \| Array[String]` | Required |
|
|
509
591
|
| `sender` | `String` | Required |
|
|
510
592
|
| `text` | `String` | Required |
|
|
511
593
|
|
|
@@ -539,14 +621,14 @@ Use the international phone format and an approved sender. Sending is never auto
|
|
|
539
621
|
| Keyword | Ruby type | Presence |
|
|
540
622
|
| --- | --- | --- |
|
|
541
623
|
| `id` | `id` | Required |
|
|
542
|
-
| `sender_name` | `String` | Optional, omitted |
|
|
543
|
-
| `sender_email` | `String` | Optional, omitted |
|
|
544
|
-
| `subject` | `String` | Optional, omitted |
|
|
545
|
-
| `body` | `String` | Optional, omitted |
|
|
546
|
-
| `list_id` | `id` | Optional, omitted |
|
|
547
|
-
| `text_body` | `String` | Optional, omitted |
|
|
548
|
-
| `lang` | `String` | Optional, omitted |
|
|
549
|
-
| `categories` | `String \| Array[id]` | Optional, omitted |
|
|
624
|
+
| `sender_name` | `String \| nil` | Optional, omitted |
|
|
625
|
+
| `sender_email` | `String \| nil` | Optional, omitted |
|
|
626
|
+
| `subject` | `String \| nil` | Optional, omitted |
|
|
627
|
+
| `body` | `String \| nil` | Optional, omitted |
|
|
628
|
+
| `list_id` | `id \| nil` | Optional, omitted |
|
|
629
|
+
| `text_body` | `String \| nil` | Optional, omitted |
|
|
630
|
+
| `lang` | `String \| nil` | Optional, omitted |
|
|
631
|
+
| `categories` | `String \| Array[id] \| nil` | Optional, omitted |
|
|
550
632
|
|
|
551
633
|
**Result:** Object with `message_id`. Retain the returned identifier because editing an already-sent message can create a new version.
|
|
552
634
|
|
|
@@ -566,7 +648,7 @@ Use the international phone format and an approved sender. Sending is never auto
|
|
|
566
648
|
| `body` | `String` | Required |
|
|
567
649
|
| `list_id` | `id` | Required |
|
|
568
650
|
|
|
569
|
-
**Result:** Empty JSON result on success.
|
|
651
|
+
**Result:** Empty JSON result on success. Named calls normalize an empty legacy array to an empty record; `data` retains the wire shape. Updates the list confirmation message.
|
|
570
652
|
|
|
571
653
|
</details>
|
|
572
654
|
|
|
@@ -579,9 +661,9 @@ Use the international phone format and an approved sender. Sending is never auto
|
|
|
579
661
|
| Keyword | Ruby type | Presence |
|
|
580
662
|
| --- | --- | --- |
|
|
581
663
|
| `username` | `String` | Required |
|
|
582
|
-
| `domain` | `String` | Optional, omitted |
|
|
583
|
-
| `limit` | `Integer` | Optional,
|
|
584
|
-
| `offset` | `Integer` | Optional, omitted |
|
|
664
|
+
| `domain` | `String \| nil` | Optional, omitted |
|
|
665
|
+
| `limit` | `Integer \| nil` | Optional, defaults to 100 |
|
|
666
|
+
| `offset` | `Integer \| nil` | Optional, omitted |
|
|
585
667
|
|
|
586
668
|
**Result:** Array of groups containing `status` and `domains`; each domain has fields such as `Domain` and `Status`. Preserve the upstream capitalization. Pagination counts domains, not groups.
|
|
587
669
|
|
|
@@ -610,9 +692,9 @@ Use the international phone format and an approved sender. Sending is never auto
|
|
|
610
692
|
| Keyword | Ruby type | Presence |
|
|
611
693
|
| --- | --- | --- |
|
|
612
694
|
| `campaign_id` | `id` | Required |
|
|
613
|
-
| `notify_url` | `String` | Optional, omitted |
|
|
614
|
-
| `changed_since` | `String` | Optional, omitted |
|
|
615
|
-
| `field_ids` | `Array[id]` | Optional, omitted |
|
|
695
|
+
| `notify_url` | `String \| nil` | Optional, omitted |
|
|
696
|
+
| `changed_since` | `String \| Time \| nil` | Optional, omitted |
|
|
697
|
+
| `field_ids` | `Array[id] \| nil` | Optional, omitted |
|
|
616
698
|
|
|
617
699
|
**Result:** Object with `task_uuid` and initial `status`, followed by a download URL when the asynchronous report completes.
|
|
618
700
|
|
|
@@ -640,14 +722,14 @@ Use the international phone format and an approved sender. Sending is never auto
|
|
|
640
722
|
|
|
641
723
|
| Keyword | Ruby type | Presence |
|
|
642
724
|
| --- | --- | --- |
|
|
643
|
-
| `date_from` | `String` | Required |
|
|
644
|
-
| `date_to` | `String` | Required |
|
|
645
|
-
| `limit` | `Integer` | Optional,
|
|
646
|
-
| `offset` | `Integer` | Optional, omitted |
|
|
725
|
+
| `date_from` | `String \| Time` | Required |
|
|
726
|
+
| `date_to` | `String \| Time` | Required |
|
|
727
|
+
| `limit` | `Integer \| nil` | Optional, defaults to 100 |
|
|
728
|
+
| `offset` | `Integer \| nil` | Optional, omitted |
|
|
647
729
|
|
|
648
730
|
**Result:** Array of message objects, including identifiers, content, sender information, and version metadata. Field availability depends on email versus SMS.
|
|
649
731
|
|
|
650
|
-
Date filters use UTC `YYYY-MM-DD HH:MM
|
|
732
|
+
Date filters use UTC `YYYY-MM-DD HH:MM`. `limit` is 1 to 100 (default 50), and `offset` starts at zero.
|
|
651
733
|
|
|
652
734
|
</details>
|
|
653
735
|
|
|
@@ -660,7 +742,7 @@ Date filters use UTC `YYYY-MM-DD HH:MM:SS`. `limit` is 1 to 100 (default 50), an
|
|
|
660
742
|
| Keyword | Ruby type | Presence |
|
|
661
743
|
| --- | --- | --- |
|
|
662
744
|
| `campaign_id` | `id` | Required |
|
|
663
|
-
| `group` | `flag` | Optional, omitted |
|
|
745
|
+
| `group` | `flag \| nil` | Optional, omitted |
|
|
664
746
|
|
|
665
747
|
**Result:** Object with `fields` (column names) and `data` (rows). Interpret each row using the matching column index.
|
|
666
748
|
|
|
@@ -674,10 +756,10 @@ Date filters use UTC `YYYY-MM-DD HH:MM:SS`. `limit` is 1 to 100 (default 50), an
|
|
|
674
756
|
|
|
675
757
|
| Keyword | Ruby type | Presence |
|
|
676
758
|
| --- | --- | --- |
|
|
677
|
-
| `date_from` | `String` | Required |
|
|
678
|
-
| `date_to` | `String` | Required |
|
|
679
|
-
| `limit` | `Integer` | Optional,
|
|
680
|
-
| `offset` | `Integer` | Optional, omitted |
|
|
759
|
+
| `date_from` | `String \| Time` | Required |
|
|
760
|
+
| `date_to` | `String \| Time` | Required |
|
|
761
|
+
| `limit` | `Integer \| nil` | Optional, defaults to 100 |
|
|
762
|
+
| `offset` | `Integer \| nil` | Optional, omitted |
|
|
681
763
|
|
|
682
764
|
**Result:** Array of message summary objects. Use `get_message` when message content is needed.
|
|
683
765
|
|
|
@@ -693,10 +775,10 @@ Date filters use UTC `YYYY-MM-DD HH:MM:SS`. `limit` is 1 to 100 (default 50), an
|
|
|
693
775
|
|
|
694
776
|
| Keyword | Ruby type | Presence |
|
|
695
777
|
| --- | --- | --- |
|
|
696
|
-
| `from` | `String` | Required |
|
|
697
|
-
| `to` | `String` | Optional, omitted |
|
|
698
|
-
| `limit` | `Integer` | Optional,
|
|
699
|
-
| `offset` | `Integer` | Optional, omitted |
|
|
778
|
+
| `from` | `String \| Time` | Required |
|
|
779
|
+
| `to` | `String \| Time \| nil` | Optional, omitted |
|
|
780
|
+
| `limit` | `Integer \| nil` | Optional, defaults to 100 |
|
|
781
|
+
| `offset` | `Integer \| nil` | Optional, omitted |
|
|
700
782
|
|
|
701
783
|
**Result:** Array of campaign objects with identifiers and campaign metadata. Supports offset pagination.
|
|
702
784
|
|
|
@@ -743,9 +825,9 @@ Date filters use UTC `YYYY-MM-DD HH:MM:SS`. `limit` is 1 to 100 (default 50), an
|
|
|
743
825
|
| `title` | `String` | Required |
|
|
744
826
|
| `subject` | `String` | Required |
|
|
745
827
|
| `body` | `String` | Required |
|
|
746
|
-
| `description` | `String` | Optional, omitted |
|
|
747
|
-
| `text_body` | `String` | Optional, omitted |
|
|
748
|
-
| `lang` | `String` | Optional, omitted |
|
|
828
|
+
| `description` | `String \| nil` | Optional, omitted |
|
|
829
|
+
| `text_body` | `String \| nil` | Optional, omitted |
|
|
830
|
+
| `lang` | `String \| nil` | Optional, omitted |
|
|
749
831
|
|
|
750
832
|
**Result:** Object with the new template `id`.
|
|
751
833
|
|
|
@@ -761,7 +843,7 @@ Date filters use UTC `YYYY-MM-DD HH:MM:SS`. `limit` is 1 to 100 (default 50), an
|
|
|
761
843
|
| --- | --- | --- |
|
|
762
844
|
| `template_id` | `id` | Required |
|
|
763
845
|
|
|
764
|
-
**Result:** Empty JSON result on success.
|
|
846
|
+
**Result:** Empty JSON result on success. Named calls normalize an empty legacy array to an empty record; `data` retains the wire shape.
|
|
765
847
|
|
|
766
848
|
</details>
|
|
767
849
|
|
|
@@ -773,8 +855,8 @@ Date filters use UTC `YYYY-MM-DD HH:MM:SS`. `limit` is 1 to 100 (default 50), an
|
|
|
773
855
|
|
|
774
856
|
| Keyword | Ruby type | Presence |
|
|
775
857
|
| --- | --- | --- |
|
|
776
|
-
| `template_id` | `id` | Optional, omitted |
|
|
777
|
-
| `system_template_id` | `id` | Optional, omitted |
|
|
858
|
+
| `template_id` | `id \| nil` | Optional, omitted |
|
|
859
|
+
| `system_template_id` | `id \| nil` | Optional, omitted |
|
|
778
860
|
|
|
779
861
|
**Result:** Object describing the selected template. User and system templates can have different fields; content fields include `subject`, `body`, and `lang_code` where applicable.
|
|
780
862
|
|
|
@@ -790,11 +872,11 @@ Provide `template_id` or `system_template_id`; neither is required individually,
|
|
|
790
872
|
|
|
791
873
|
| Keyword | Ruby type | Presence |
|
|
792
874
|
| --- | --- | --- |
|
|
793
|
-
| `type` | `
|
|
794
|
-
| `date_from` | `String` | Optional, omitted |
|
|
795
|
-
| `date_to` | `String` | Optional, omitted |
|
|
796
|
-
| `limit` | `Integer` | Optional,
|
|
797
|
-
| `offset` | `Integer` | Optional, omitted |
|
|
875
|
+
| `type` | `template_type \| nil` | Optional, omitted |
|
|
876
|
+
| `date_from` | `String \| Time \| nil` | Optional, omitted |
|
|
877
|
+
| `date_to` | `String \| Time \| nil` | Optional, omitted |
|
|
878
|
+
| `limit` | `Integer \| nil` | Optional, defaults to 100 |
|
|
879
|
+
| `offset` | `Integer \| nil` | Optional, omitted |
|
|
798
880
|
|
|
799
881
|
**Result:** Array of template objects with identifiers, titles, content, and metadata. User-only fields include `body`; system templates can provide preview URLs instead.
|
|
800
882
|
|
|
@@ -810,11 +892,11 @@ Provide `template_id` or `system_template_id`; neither is required individually,
|
|
|
810
892
|
|
|
811
893
|
| Keyword | Ruby type | Presence |
|
|
812
894
|
| --- | --- | --- |
|
|
813
|
-
| `type` | `
|
|
814
|
-
| `date_from` | `String` | Optional, omitted |
|
|
815
|
-
| `date_to` | `String` | Optional, omitted |
|
|
816
|
-
| `limit` | `Integer` | Optional,
|
|
817
|
-
| `offset` | `Integer` | Optional, omitted |
|
|
895
|
+
| `type` | `template_type \| nil` | Optional, omitted |
|
|
896
|
+
| `date_from` | `String \| Time \| nil` | Optional, omitted |
|
|
897
|
+
| `date_to` | `String \| Time \| nil` | Optional, omitted |
|
|
898
|
+
| `limit` | `Integer \| nil` | Optional, defaults to 100 |
|
|
899
|
+
| `offset` | `Integer \| nil` | Optional, omitted |
|
|
818
900
|
|
|
819
901
|
**Result:** Array of template summary objects. Use `get_template` for a selected template.
|
|
820
902
|
|
|
@@ -831,12 +913,12 @@ Provide `template_id` or `system_template_id`; neither is required individually,
|
|
|
831
913
|
| Keyword | Ruby type | Presence |
|
|
832
914
|
| --- | --- | --- |
|
|
833
915
|
| `template_id` | `id` | Required |
|
|
834
|
-
| `title` | `String` | Optional, omitted |
|
|
835
|
-
| `description` | `String` | Optional, omitted |
|
|
836
|
-
| `subject` | `String` | Optional, omitted |
|
|
837
|
-
| `body` | `String` | Optional, omitted |
|
|
838
|
-
| `text_body` | `String` | Optional, omitted |
|
|
839
|
-
| `lang` | `String` | Optional, omitted |
|
|
916
|
+
| `title` | `String \| nil` | Optional, omitted |
|
|
917
|
+
| `description` | `String \| nil` | Optional, omitted |
|
|
918
|
+
| `subject` | `String \| nil` | Optional, omitted |
|
|
919
|
+
| `body` | `String \| nil` | Optional, omitted |
|
|
920
|
+
| `text_body` | `String \| nil` | Optional, omitted |
|
|
921
|
+
| `lang` | `String \| nil` | Optional, omitted |
|
|
840
922
|
|
|
841
923
|
**Result:** Object with the updated template `id`.
|
|
842
924
|
|
|
@@ -852,7 +934,7 @@ Provide `template_id` or `system_template_id`; neither is required individually,
|
|
|
852
934
|
| --- | --- | --- |
|
|
853
935
|
| `name` | `String` | Required |
|
|
854
936
|
| `type` | `String` | Required |
|
|
855
|
-
| `public_name` | `String` | Optional, omitted |
|
|
937
|
+
| `public_name` | `String \| nil` | Optional, omitted |
|
|
856
938
|
|
|
857
939
|
**Result:** Object with the new field `id`.
|
|
858
940
|
|
|
@@ -868,7 +950,7 @@ Provide `template_id` or `system_template_id`; neither is required individually,
|
|
|
868
950
|
| --- | --- | --- |
|
|
869
951
|
| `id` | `id` | Required |
|
|
870
952
|
|
|
871
|
-
**Result:** Empty JSON result on success.
|
|
953
|
+
**Result:** Empty JSON result on success. Named calls normalize an empty legacy array to an empty record; `data` retains the wire shape.
|
|
872
954
|
|
|
873
955
|
</details>
|
|
874
956
|
|
|
@@ -882,7 +964,7 @@ Provide `template_id` or `system_template_id`; neither is required individually,
|
|
|
882
964
|
| --- | --- | --- |
|
|
883
965
|
| `id` | `id` | Required |
|
|
884
966
|
|
|
885
|
-
**Result:** Empty JSON result on success.
|
|
967
|
+
**Result:** Empty JSON result on success. Named calls normalize an empty legacy array to an empty record; `data` retains the wire shape.
|
|
886
968
|
|
|
887
969
|
</details>
|
|
888
970
|
|
|
@@ -920,7 +1002,7 @@ No operation arguments.
|
|
|
920
1002
|
| --- | --- | --- |
|
|
921
1003
|
| `id` | `id` | Required |
|
|
922
1004
|
| `name` | `String` | Required |
|
|
923
|
-
| `public_name` | `String` | Optional, omitted |
|
|
1005
|
+
| `public_name` | `String \| nil` | Optional, omitted |
|
|
924
1006
|
|
|
925
1007
|
**Result:** The documented top-level Object contains the updated field `id`. Legacy `result` envelopes are also accepted.
|
|
926
1008
|
|
|
@@ -981,7 +1063,7 @@ No operation arguments.
|
|
|
981
1063
|
| --- | --- | --- |
|
|
982
1064
|
| `id` | `id` | Required |
|
|
983
1065
|
|
|
984
|
-
**Result:** Empty JSON result on success.
|
|
1066
|
+
**Result:** Empty JSON result on success. Named calls normalize an empty legacy array to an empty record; `data` retains the wire shape.
|
|
985
1067
|
|
|
986
1068
|
</details>
|
|
987
1069
|
|
|
@@ -1008,11 +1090,11 @@ No operation arguments.
|
|
|
1008
1090
|
| Keyword | Ruby type | Presence |
|
|
1009
1091
|
| --- | --- | --- |
|
|
1010
1092
|
| `subscriber_id` | `id` | Required |
|
|
1011
|
-
| `limit` | `Integer` | Optional,
|
|
1012
|
-
| `offset` | `Integer` | Optional, omitted |
|
|
1013
|
-
| `order_type` | `
|
|
1014
|
-
| `order_by` | `
|
|
1015
|
-
| `is_pinned` | `flag` | Optional, omitted |
|
|
1093
|
+
| `limit` | `Integer \| nil` | Optional, defaults to 100 |
|
|
1094
|
+
| `offset` | `Integer \| nil` | Optional, omitted |
|
|
1095
|
+
| `order_type` | `note_order \| nil` | Optional, omitted |
|
|
1096
|
+
| `order_by` | `note_field \| nil` | Optional, omitted |
|
|
1097
|
+
| `is_pinned` | `flag \| nil` | Optional, omitted |
|
|
1016
1098
|
|
|
1017
1099
|
**Result:** Array of note objects for the subscriber. Supports offset pagination.
|
|
1018
1100
|
|
|
@@ -1034,13 +1116,93 @@ Supply 1 to 25 events. Each event requires a `name` of 1 to 40 characters and an
|
|
|
1034
1116
|
|
|
1035
1117
|
</details>
|
|
1036
1118
|
|
|
1119
|
+
## Typed result readers
|
|
1120
|
+
|
|
1121
|
+
Records support `[]`, `fetch`, and `dig` with exact upstream keys. `to_h` returns a detached mutable copy.
|
|
1122
|
+
Documented optional fields return `nil`; unknown fields remain accessible through lookup and the raw response.
|
|
1123
|
+
Object responses expose their result readers directly. Collection elements expose the readers in this table.
|
|
1124
|
+
|
|
1125
|
+
| Result | Readers |
|
|
1126
|
+
| --- | --- |
|
|
1127
|
+
| `Campaign` | `status`, `subject`, `id` |
|
|
1128
|
+
| `CampaignCreated` | `count`, `campaign_id`, `status` |
|
|
1129
|
+
| `CampaignStats` | `total`, `sent`, `delivered`, `read_unique`, `read_all`, `clicked_unique`, `clicked_all`, `unsubscribed`, `spam` |
|
|
1130
|
+
| `Contact` | `email`, `email_address`, `phone`, `phone_number`, `lists`, `fields` |
|
|
1131
|
+
| `ContactCount` | `count` |
|
|
1132
|
+
| `ContactFields` | `field_values` |
|
|
1133
|
+
| `ContactList` | `status`, `added_at`, `id` |
|
|
1134
|
+
| `EmailContact` | `email`, `status`, `availability`, `added_at`, `last_send_datetime`, `last_delivery_datetime`, `last_read_datetime`, `last_click_datetime`, `rating` |
|
|
1135
|
+
| `EmailDelivery` | `id`, `status` |
|
|
1136
|
+
| `EventResult` | `complete?`, `partial?`, `uncertain?`, `failures` |
|
|
1137
|
+
| `Failure` | `index`, `code`, `message`, `warning?`, `with_offset` |
|
|
1138
|
+
| `Field` | `name`, `type`, `id` |
|
|
1139
|
+
| `Hook` | `url`, `event_format`, `max_parallel`, `single_event`, `status`, `events`, `id` |
|
|
1140
|
+
| `IdentifierRecord` | `id` |
|
|
1141
|
+
| `ImportResult` | `row_warnings`, `inserted`, `updated`, `deleted`, `new_emails`, `total`, `invalid`, `complete?`, `partial?`, `uncertain?`, `failures` |
|
|
1142
|
+
| `List` | `title`, `id` |
|
|
1143
|
+
| `Message` | `subject`, `body`, `sender_name`, `sender_email`, `id` |
|
|
1144
|
+
| `MessageCreated` | `message_id` |
|
|
1145
|
+
| `MessageNotice` | `message` |
|
|
1146
|
+
| `MessageVersion` | `message_id`, `actual_version_id` |
|
|
1147
|
+
| `Note` | `user_id`, `subscriber_id`, `origin`, `is_pinned`, `created_at`, `updated_at`, `pinned_at`, `content`, `id` |
|
|
1148
|
+
| `OptionalIdentifier` | `id` |
|
|
1149
|
+
| `PhoneContact` | `phone`, `status`, `availability`, `added_at` |
|
|
1150
|
+
| `RecipientResult` | `id`, `index`, `email`, `failures`, `accepted?` |
|
|
1151
|
+
| `SendResult` | `accepted_recipients`, `rejected_recipients`, `unknown_recipients`, `accepted_ids`, `recipients`, `email_id`, `complete?`, `partial?`, `uncertain?`, `failures` |
|
|
1152
|
+
| `SenderDomain` | `domain`, `status`, `key` |
|
|
1153
|
+
| `SenderDomainGroup` | `status`, `domains` |
|
|
1154
|
+
| `SmsReceipt` | `sms_id`, `price`, `currency` |
|
|
1155
|
+
| `Status` | `status` |
|
|
1156
|
+
| `Subscription` | `person_id` |
|
|
1157
|
+
| `Tag` | `name`, `id` |
|
|
1158
|
+
| `TaskResult` | `task_uuid`, `status`, `file_to_download` |
|
|
1159
|
+
| `Template` | `title`, `subject`, `body`, `id` |
|
|
1160
|
+
| `TotalContacts` | `total` |
|
|
1161
|
+
| `WebVersion` | `letter_id`, `web_letter_link` |
|
|
1162
|
+
| `WebhookEvent` | `event_name`, `event_time`, `event_data` |
|
|
1163
|
+
| `WebhookNotification` | `users`, `events` |
|
|
1164
|
+
| `WebhookUser` | `login`, `events` |
|
|
1165
|
+
|
|
1166
|
+
Report responses also expose `raise_for_partial_failure!`.
|
|
1167
|
+
A `BatchReport` exposes `responses`, `completed_batches`, `total`, `invalid`, `failures`, `complete?`, `partial?`, and `uncertain?`.
|
|
1168
|
+
Its totals return `nil` when the outcome does not provide reliable import counts.
|
|
1169
|
+
Task handles expose `task_uuid`, `wait`, and `download_to`; their result retains the original task fields. Polling request errors keep their original error class and expose `task_uuid` plus `last_response` (nil before any observed task state).
|
|
1170
|
+
|
|
1037
1171
|
## Documentation decisions
|
|
1038
1172
|
|
|
1173
|
+
### Webhook management
|
|
1174
|
+
|
|
1175
|
+
<a id="set_hook"></a>
|
|
1176
|
+
#### `set_hook`
|
|
1177
|
+
|
|
1178
|
+
| Keyword | Ruby type | Presence |
|
|
1179
|
+
| --- | --- | --- |
|
|
1180
|
+
| `hook_url` | `String` | Required |
|
|
1181
|
+
| `events` | `Hash[String \| Symbol, String \| Array[String \| Integer]]` | Required |
|
|
1182
|
+
| `event_format` | `:json_post \| :json_post_gzip \| :http_get \| String` | Optional, defaults to json_post_gzip |
|
|
1183
|
+
| `max_parallel` | `Integer?` | Optional, omitted |
|
|
1184
|
+
| `single_event` | `flag` | Optional, defaults to false (0 on the wire) |
|
|
1185
|
+
| `status` | `:active \| :disabled \| String` | Optional, defaults to active |
|
|
1186
|
+
|
|
1187
|
+
<a id="list_hooks"></a>
|
|
1188
|
+
#### `list_hooks`
|
|
1189
|
+
|
|
1190
|
+
No operation arguments.
|
|
1191
|
+
|
|
1192
|
+
<a id="remove_hook"></a>
|
|
1193
|
+
#### `remove_hook`
|
|
1194
|
+
|
|
1195
|
+
| Keyword | Ruby type | Presence |
|
|
1196
|
+
| --- | --- | --- |
|
|
1197
|
+
| `hook_url` | `String` | Required |
|
|
1198
|
+
|
|
1199
|
+
See the [receiver guide](webhooks.md) for registration behavior and bounded verification.
|
|
1200
|
+
|
|
1039
1201
|
Successful `sendTestEmail` and `updateField` examples omit the `result` envelope. These two operations also accept their documented top-level success fields. Other operations still require `result`, and `error` always takes precedence.
|
|
1040
1202
|
|
|
1041
1203
|
|
|
1042
1204
|
1. **D1:** The supplied [OpenAPI repository](https://gitflic.ru/project/unisender/unigo-openapi) targets UniSender Go, which has a different host and protocol. This gem does not use that specification.
|
|
1043
|
-
2. **D2:** Contact exports and delivery reports use `async/exportContacts` and `async/getCampaignDeliveryStats`. Both share `async/getTaskResult`. The gem returns the download URL
|
|
1205
|
+
2. **D2:** Contact exports and delivery reports use `async/exportContacts` and `async/getCampaignDeliveryStats`. Both share `async/getTaskResult`. The gem returns the download URL. Only an explicit `download_to` requests it, using a separate connection without API credentials.
|
|
1044
1206
|
3. **D3:** Note page titles misspell create and update operations. Their request examples use `createSubscriberNote` and `updateSubscriberNote`; the gem follows those request URLs.
|
|
1045
1207
|
4. **D4:** Event Tracking's endpoint definition specifies `https://event.unisender.com/v1/events/`, but its examples omit `/v1`. The gem follows the endpoint definition. The page also shows both a string `error` and structured `details`; `EventError#details` accepts either representation. HTTP 400 can mean partial acceptance.
|
|
1046
1208
|
5. **D5:** The create-email page allows templates to supply subject and body. Both template selectors satisfy this alternative; the gem does not invent precedence if both are supplied. Its syntax lists `categories`, although its argument table omits it; the gem accepts that documented keyword.
|
|
@@ -1049,15 +1211,38 @@ Successful `sendTestEmail` and `updateField` examples omit the `result` envelope
|
|
|
1049
1211
|
|
|
1050
1212
|
## Convenience operations
|
|
1051
1213
|
|
|
1214
|
+
`client.validate!(operation, **arguments)` checks named request arguments, defaults, normalization, and encoding without networking.
|
|
1215
|
+
It returns `true` or raises a validation error. It also accepts `:track_events` and `:send_campaign`.
|
|
1216
|
+
Low-level requests and multi-request iterators are not supported. Import validation consumes supplied records up to the direct-request bound.
|
|
1217
|
+
|
|
1052
1218
|
| Helper | Behavior |
|
|
1053
1219
|
| --- | --- |
|
|
1054
1220
|
| `each_page(method, page_size: 100, max_pages: 1000, **params)` | Lazy Enumerator of responses for `get_campaigns`, `get_messages`, `list_messages`, `get_templates`, `list_templates`, `get_sender_domain_list`, and `get_subscriber_notes`. An optional `offset` starts iteration. Stops at a short or empty page; raises at the page bound. Offset pagination is not a server snapshot. |
|
|
1055
|
-
| `import_contacts_in_batches(
|
|
1056
|
-
| `track_events_in_batches(events:, batch_size: 25)` |
|
|
1221
|
+
| `import_contacts_in_batches(records: ..., batch_size: 500, ...)` | Immediate sequential import returning a `BatchReport`; `each_import_batch` is the lazy equivalent. Also accepts legacy `field_names:` plus `data:`, and `overwrite_tags`, `overwrite_lists`, and `telegram_bot_channel_id`. Stops on request failures or a nonzero `invalid` count. |
|
|
1222
|
+
| `track_events_in_batches(events:, batch_size: 25)` | Immediate sequential event batches returning a `BatchReport`; `each_event_batch` is the lazy equivalent. Each request must also meet the 130 KiB payload limit. Batches also split automatically when the next event would exceed the byte limit. |
|
|
1057
1223
|
| `wait_for_task(task_uuid:, interval: 1, timeout: 60)` | Polls existing tasks until completion, with a monotonic deadline. Raises on an unknown task state. Deadlines are checked between requests; an in-flight request remains bounded by transport timeouts. |
|
|
1058
1224
|
|
|
1059
|
-
`each_page` accepts the same operation keywords as the corresponding named method, except that `page_size` replaces `limit`. Unknown keywords, non-symbol keys, and missing or empty required values raise `ArgumentError` when
|
|
1225
|
+
`each_page` accepts the same operation keywords as the corresponding named method, except that `page_size` replaces `limit`. Unknown keywords, non-symbol keys, and missing or empty required values raise `ArgumentError` when the iterator is constructed, before any request. Direct named calls reject invalid arguments immediately. The low-level `request` method retains its existing parameter handling.
|
|
1226
|
+
|
|
1227
|
+
Pagination additionally requires a positive integer page size within the method's documented limit, a positive integer `max_pages`, and a nonnegative integer `offset`. Named paginated reads use the same local validation for `limit` and `offset`. Each yielded response preserves its warnings and metadata.
|
|
1060
1228
|
|
|
1061
|
-
|
|
1229
|
+
Batch helper failures raise `BatchError`. Its `completed_responses` contains earlier successful batches, `failed_range` is the zero-based, end-exclusive input range with an uncertain or failed outcome, and `error` contains the original failure. A failed batch can still contain accepted records. Helpers do not replay batches or roll back earlier changes. Source exceptions also retain completed responses; an unknown unsent source range can be empty at the next offset.
|
|
1062
1230
|
|
|
1063
|
-
|
|
1231
|
+
All batch helpers accept `retention: :full | :summary` and `on_progress:`. Full history is the default. Summary mode retains counts and failed-response details, not successful payloads. `client.with_execution(timeout:, cancellation:, instrumentation:)` creates a cooperative budget for related work. See [execution and recovery](execution.md) for checkpoint and lifetime contracts.
|
|
1232
|
+
|
|
1233
|
+
## Optional workflow helpers
|
|
1234
|
+
|
|
1235
|
+
| Helper | Contract |
|
|
1236
|
+
| --- | --- |
|
|
1237
|
+
| `Client.new(persistent: true)` | Reuses verified TLS connections to the marketing and Event Tracking origins. Requests on one transport are serialized. Idle connections expire after 30 seconds. A PID change discards inherited connections. Failed requests are not replayed by the transport. |
|
|
1238
|
+
| `client.close` | Idempotent. Rejects subsequent client requests and closes owned persistent connections. It does not close an injected transport. |
|
|
1239
|
+
| `RateLimiter.new(global: [count, seconds], methods: { "wireName" => [count, seconds] })` | Sliding windows apply before every marketing attempt, including retries. Share the instance to share a process-local budget. The injected `clock:` and `sleeper:` are optional. Event Tracking bypasses this limiter. |
|
|
1240
|
+
| `RateLimiter.unisender` | Uses the global and method-specific limits documented at the linked [request limits page](https://www.unisender.com/ru/support/api/common/api-limits/). It is opt-in and cannot account for requests from other processes. |
|
|
1241
|
+
| `Attachment.new(filename:, bytes:)` | Immutable binary snapshot. `from_path(path, filename:)` defaults to the basename. `from_io(io, filename:)` reads from the current position and leaves the IO open. Duplicate filenames and invalid form-field delimiters are rejected. |
|
|
1242
|
+
| `send_campaign(message:, campaign: {})` | Validates keyword sets and required values before either request. `message:` takes create-email options; `campaign:` takes create-campaign options except `message_id`. Returns `CampaignReceipt(message:, campaign:)`. A second-step failure raises `CampaignWorkflowError` with `message_response` and the underlying `error`. No rollback or automatic replay. |
|
|
1243
|
+
| `completed.download_to(io, max_bytes:, downloader: Downloader.new)` | Requires a completed task with a download URL. Returns `DownloadReceipt` with `bytes_written` and `http_status`. Never closes the IO or polls implicitly. |
|
|
1244
|
+
| `Downloader.new(open_timeout: 5, read_timeout: 60, write_timeout: 30)` | Separate credential-free HTTPS GET, no redirects or retries. Resolves once, rejects private or mixed public/private answers, and pins the chosen address while retaining hostname certificate verification. Downloads stream within the caller's byte limit; timeout values bound connection and IO operations, not the total transfer duration. |
|
|
1245
|
+
|
|
1246
|
+
`DownloadError` exposes `reason`, `bytes_written`, and optional `http_status`. Reasons include `invalid_url`, `blocked_destination`, `http_error`, `too_large`, `incomplete`, `write_failed`, and `transport`. Signed URLs do not appear in error messages. Failed downloads can leave partial data in the caller's IO. The caller decides whether to discard or keep it. Custom downloader `resolver:` and `http_factory:` callbacks are trusted test seams and must preserve destination validation and TLS verification in production.
|
|
1247
|
+
|
|
1248
|
+
Downloads conservatively reject special-use, translation, and tunneling address ranges, including NAT64 and 6to4. Ordinary global-unicast IPv6 addresses are accepted; a special-purpose prefix is not accepted merely because a local router can forward it. Address policy follows the [IANA IPv6](https://www.iana.org/assignments/iana-ipv6-special-registry/) and [IPv4](https://www.iana.org/assignments/iana-ipv4-special-registry/) registries.
|