loops_sdk 2.2.0 → 2.3.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/README.md +597 -96
- data/lib/loops_sdk/audience_segments.rb +15 -0
- data/lib/loops_sdk/campaign_groups.rb +25 -0
- data/lib/loops_sdk/campaigns.rb +20 -4
- data/lib/loops_sdk/email_messages.rb +35 -2
- data/lib/loops_sdk/transactional.rb +24 -1
- data/lib/loops_sdk/transactional_groups.rb +25 -0
- data/lib/loops_sdk/uploads.rb +66 -0
- data/lib/loops_sdk/version.rb +1 -1
- data/lib/loops_sdk/workflows.rb +19 -0
- data/lib/loops_sdk.rb +5 -0
- metadata +7 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5a4fac371d3bbc89f778265ecb287032e0ce08846a688b61887a64f27e30f8f4
|
|
4
|
+
data.tar.gz: 4c0647edf1dcebf7927232332ad5d92d8114c5ce8b291b1cbffc0c4dd145455e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 592a434bc0dd7d9c19c2b209eacd2463373cbeca1ed6d67e8fb376443084ae1e3c24ef95b2ee85d225e6c4ee544badd16fe34b6b80c262192817c77d501cf8a3
|
|
7
|
+
data.tar.gz: 2e979c1b6ddd315fd3adc6d28fedd69bf19322207ca66bf85eef4ea799d4f94dce01ffb55205fe23dcd7da872e132e976a83f11fcb6d0755744388b990a528a9
|
data/README.md
CHANGED
|
@@ -114,8 +114,13 @@ You can use custom contact properties in API calls. Please make sure to [add cus
|
|
|
114
114
|
- [ContactProperties.list()](#contactpropertieslist)
|
|
115
115
|
- [MailingLists.list()](#mailinglistslist)
|
|
116
116
|
- [Events.send()](#eventssend)
|
|
117
|
-
- [Transactional.send()](#transactionalsend)
|
|
118
117
|
- [Transactional.list()](#transactionallist)
|
|
118
|
+
- [Transactional.create()](#transactionalcreate)
|
|
119
|
+
- [Transactional.get()](#transactionalget)
|
|
120
|
+
- [Transactional.update()](#transactionalupdate)
|
|
121
|
+
- [Transactional.ensure_draft()](#transactionalensure_draft)
|
|
122
|
+
- [Transactional.publish()](#transactionalpublish)
|
|
123
|
+
- [Transactional.send()](#transactionalsend)
|
|
119
124
|
- [DedicatedSendingIps.list()](#dedicatedsendingipslist)
|
|
120
125
|
- [Themes.list()](#themeslist)
|
|
121
126
|
- [Themes.get()](#themesget)
|
|
@@ -125,8 +130,23 @@ You can use custom contact properties in API calls. Please make sure to [add cus
|
|
|
125
130
|
- [Campaigns.create()](#campaignscreate)
|
|
126
131
|
- [Campaigns.get()](#campaignsget)
|
|
127
132
|
- [Campaigns.update()](#campaignsupdate)
|
|
133
|
+
- [CampaignGroups.list()](#campaigngroupslist)
|
|
134
|
+
- [CampaignGroups.create()](#campaigngroupscreate)
|
|
135
|
+
- [CampaignGroups.get()](#campaigngroupsget)
|
|
136
|
+
- [CampaignGroups.update()](#campaigngroupsupdate)
|
|
137
|
+
- [AudienceSegments.list()](#audiencesegmentslist)
|
|
138
|
+
- [AudienceSegments.get()](#audiencesegmentsget)
|
|
139
|
+
- [Workflows.list()](#workflowslist)
|
|
140
|
+
- [Workflows.get()](#workflowsget)
|
|
141
|
+
- [Workflows.get_node()](#workflowsget_node)
|
|
128
142
|
- [EmailMessages.get()](#emailmessagesget)
|
|
129
143
|
- [EmailMessages.update()](#emailmessagesupdate)
|
|
144
|
+
- [EmailMessages.preview()](#emailmessagespreview)
|
|
145
|
+
- [TransactionalGroups.list()](#transactionalgroupslist)
|
|
146
|
+
- [TransactionalGroups.create()](#transactionalgroupscreate)
|
|
147
|
+
- [TransactionalGroups.get()](#transactionalgroupsget)
|
|
148
|
+
- [TransactionalGroups.update()](#transactionalgroupsupdate)
|
|
149
|
+
- [Uploads.upload()](#uploadsupload)
|
|
130
150
|
|
|
131
151
|
---
|
|
132
152
|
|
|
@@ -206,7 +226,7 @@ This method will return a success or error message:
|
|
|
206
226
|
```json
|
|
207
227
|
{
|
|
208
228
|
"success": true,
|
|
209
|
-
"id": "
|
|
229
|
+
"id": "cll6b3i8901a9jx0oyktl2m4u"
|
|
210
230
|
}
|
|
211
231
|
```
|
|
212
232
|
|
|
@@ -270,7 +290,7 @@ This method will return a success or error message:
|
|
|
270
290
|
```json
|
|
271
291
|
{
|
|
272
292
|
"success": true,
|
|
273
|
-
"id": "
|
|
293
|
+
"id": "cll6b3i8901a9jx0oyktl2m4u"
|
|
274
294
|
}
|
|
275
295
|
```
|
|
276
296
|
|
|
@@ -726,6 +746,180 @@ This method will return a success or error:
|
|
|
726
746
|
|
|
727
747
|
---
|
|
728
748
|
|
|
749
|
+
### Transactional.list()
|
|
750
|
+
|
|
751
|
+
List transactional emails, most recently created first.
|
|
752
|
+
|
|
753
|
+
[API Reference](https://loops.so/docs/api-reference/list-transactional-emails)
|
|
754
|
+
|
|
755
|
+
#### Parameters
|
|
756
|
+
|
|
757
|
+
| Name | Type | Required | Notes |
|
|
758
|
+
| --------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
759
|
+
| `perPage` | integer | No | How many results to return per page. Must be between 10 and 50. Defaults to 20 if omitted. |
|
|
760
|
+
| `cursor` | string | No | A cursor, to return a specific page of results. Cursors can be found from the `pagination.nextCursor` value in each response. |
|
|
761
|
+
|
|
762
|
+
#### Example
|
|
763
|
+
|
|
764
|
+
```ruby
|
|
765
|
+
response = LoopsSdk::Transactional.list
|
|
766
|
+
|
|
767
|
+
response = LoopsSdk::Transactional.list(perPage: 15, cursor: "cursor_value")
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
#### Response
|
|
771
|
+
|
|
772
|
+
```json
|
|
773
|
+
{
|
|
774
|
+
"pagination": {
|
|
775
|
+
"totalResults": 23,
|
|
776
|
+
"returnedResults": 20,
|
|
777
|
+
"perPage": 20,
|
|
778
|
+
"totalPages": 2,
|
|
779
|
+
"nextCursor": "clyo0q4wo01p59fsecyxqsh38",
|
|
780
|
+
"nextPage": "https://app.loops.so/api/v1/transactional-emails?cursor=clyo0q4wo01p59fsecyxqsh38&perPage=20"
|
|
781
|
+
},
|
|
782
|
+
"data": [
|
|
783
|
+
{
|
|
784
|
+
"id": "clfn0k1yg001imo0fdeqg30i8",
|
|
785
|
+
"name": "Welcome email",
|
|
786
|
+
"draftEmailMessageId": null,
|
|
787
|
+
"publishedEmailMessageId": "cly8k3m0n0044jpx2bghepq45",
|
|
788
|
+
"createdAt": "2023-11-06T17:48:07.249Z",
|
|
789
|
+
"updatedAt": "2023-11-06T17:48:07.249Z",
|
|
790
|
+
"dataVariables": ["confirmationUrl"]
|
|
791
|
+
}
|
|
792
|
+
]
|
|
793
|
+
}
|
|
794
|
+
```
|
|
795
|
+
|
|
796
|
+
---
|
|
797
|
+
|
|
798
|
+
### Transactional.create()
|
|
799
|
+
|
|
800
|
+
Create a transactional email. An empty draft email message is created automatically.
|
|
801
|
+
|
|
802
|
+
[API Reference](https://loops.so/docs/api-reference/create-transactional-email)
|
|
803
|
+
|
|
804
|
+
#### Parameters
|
|
805
|
+
|
|
806
|
+
| Name | Type | Required | Notes |
|
|
807
|
+
| ------------------------ | ------ | -------- | ------------------------------------------------------- |
|
|
808
|
+
| `name` | string | Yes | |
|
|
809
|
+
| `transactional_group_id` | string | No | The ID of the group to add this transactional email to. |
|
|
810
|
+
|
|
811
|
+
#### Example
|
|
812
|
+
|
|
813
|
+
```ruby
|
|
814
|
+
response = LoopsSdk::Transactional.create(name: "Welcome email")
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
#### Response
|
|
818
|
+
|
|
819
|
+
Returns the transactional email with `draftEmailMessageId` and `draftEmailMessageContentRevisionId`. Use these when updating the draft via `EmailMessages.update()`.
|
|
820
|
+
|
|
821
|
+
```json
|
|
822
|
+
{
|
|
823
|
+
"id": "clfq6dinn000yl70fgwwyp82l",
|
|
824
|
+
"name": "Welcome email",
|
|
825
|
+
"draftEmailMessageId": "cly8k3m0n0044jpx2bghepq45",
|
|
826
|
+
"draftEmailMessageContentRevisionId": "clm9n4o6p0088lrz4dijslt67",
|
|
827
|
+
"publishedEmailMessageId": null,
|
|
828
|
+
"createdAt": "2023-11-06T17:48:07.249Z",
|
|
829
|
+
"updatedAt": "2023-11-06T17:48:07.249Z",
|
|
830
|
+
"dataVariables": []
|
|
831
|
+
}
|
|
832
|
+
```
|
|
833
|
+
|
|
834
|
+
---
|
|
835
|
+
|
|
836
|
+
### Transactional.get()
|
|
837
|
+
|
|
838
|
+
Get a single transactional email by ID.
|
|
839
|
+
|
|
840
|
+
[API Reference](https://loops.so/docs/api-reference/get-transactional-email)
|
|
841
|
+
|
|
842
|
+
#### Parameters
|
|
843
|
+
|
|
844
|
+
| Name | Type | Required | Notes |
|
|
845
|
+
| ------------------ | ------ | -------- | ----- |
|
|
846
|
+
| `transactional_id` | string | Yes | |
|
|
847
|
+
|
|
848
|
+
#### Example
|
|
849
|
+
|
|
850
|
+
```ruby
|
|
851
|
+
response = LoopsSdk::Transactional.get(transactional_id: "clfq6dinn000yl70fgwwyp82l")
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
---
|
|
855
|
+
|
|
856
|
+
### Transactional.update()
|
|
857
|
+
|
|
858
|
+
Update a transactional email's name.
|
|
859
|
+
|
|
860
|
+
[API Reference](https://loops.so/docs/api-reference/update-transactional-email)
|
|
861
|
+
|
|
862
|
+
#### Parameters
|
|
863
|
+
|
|
864
|
+
| Name | Type | Required | Notes |
|
|
865
|
+
| ------------------------ | ------ | -------- | ------------------------------------------------------------ |
|
|
866
|
+
| `transactional_id` | string | Yes | |
|
|
867
|
+
| `name` | string | No | |
|
|
868
|
+
| `transactional_group_id` | string | No | The ID of the group to move this transactional email to. |
|
|
869
|
+
|
|
870
|
+
At least one field must be provided.
|
|
871
|
+
|
|
872
|
+
#### Example
|
|
873
|
+
|
|
874
|
+
```ruby
|
|
875
|
+
response = LoopsSdk::Transactional.update(
|
|
876
|
+
transactional_id: "clfq6dinn000yl70fgwwyp82l",
|
|
877
|
+
name: "Updated name"
|
|
878
|
+
)
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
---
|
|
882
|
+
|
|
883
|
+
### Transactional.ensure_draft()
|
|
884
|
+
|
|
885
|
+
Ensure a transactional email has a draft email message. If a draft already exists it is returned unchanged; otherwise a new empty draft is created.
|
|
886
|
+
|
|
887
|
+
[API Reference](https://loops.so/docs/api-reference/ensure-transactional-email-draft)
|
|
888
|
+
|
|
889
|
+
#### Parameters
|
|
890
|
+
|
|
891
|
+
| Name | Type | Required | Notes |
|
|
892
|
+
| ------------------ | ------ | -------- | ----- |
|
|
893
|
+
| `transactional_id` | string | Yes | |
|
|
894
|
+
|
|
895
|
+
#### Example
|
|
896
|
+
|
|
897
|
+
```ruby
|
|
898
|
+
response = LoopsSdk::Transactional.ensure_draft(transactional_id: "clfq6dinn000yl70fgwwyp82l")
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
---
|
|
902
|
+
|
|
903
|
+
### Transactional.publish()
|
|
904
|
+
|
|
905
|
+
Publish a transactional email's current draft. The draft becomes the published version and the draft is cleared.
|
|
906
|
+
|
|
907
|
+
[API Reference](https://loops.so/docs/api-reference/publish-transactional-email)
|
|
908
|
+
|
|
909
|
+
#### Parameters
|
|
910
|
+
|
|
911
|
+
| Name | Type | Required | Notes |
|
|
912
|
+
| ------------------ | ------ | -------- | ----- |
|
|
913
|
+
| `transactional_id` | string | Yes | |
|
|
914
|
+
|
|
915
|
+
#### Example
|
|
916
|
+
|
|
917
|
+
```ruby
|
|
918
|
+
response = LoopsSdk::Transactional.publish(transactional_id: "clfq6dinn000yl70fgwwyp82l")
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
---
|
|
922
|
+
|
|
729
923
|
### Transactional.send()
|
|
730
924
|
|
|
731
925
|
Send a transactional email to a contact. [Learn about sending transactional email](https://loops.so/docs/transactional/guide)
|
|
@@ -736,7 +930,7 @@ Send a transactional email to a contact. [Learn about sending transactional emai
|
|
|
736
930
|
|
|
737
931
|
| Name | Type | Required | Notes |
|
|
738
932
|
| ---------------------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
739
|
-
| `transactional_id`
|
|
933
|
+
| `transactional_id` | string | Yes | The ID of the transactional email to send. |
|
|
740
934
|
| `email` | string | Yes | The email address of the recipient. |
|
|
741
935
|
| `add_to_audience` | boolean | No | If `true`, a contact will be created in your audience using the `email` value (if a matching contact doesn't already exist). |
|
|
742
936
|
| `data_variables` | object | No | An object containing data as defined by the data variables added to the transactional email template.<br />Values can be of type `string` or `number`. |
|
|
@@ -819,68 +1013,6 @@ If there is a problem with the request, a descriptive error message will be retu
|
|
|
819
1013
|
|
|
820
1014
|
---
|
|
821
1015
|
|
|
822
|
-
### Transactional.list()
|
|
823
|
-
|
|
824
|
-
Get a list of published transactional emails.
|
|
825
|
-
|
|
826
|
-
[API Reference](https://loops.so/docs/api-reference/list-transactional-emails)
|
|
827
|
-
|
|
828
|
-
#### Parameters
|
|
829
|
-
|
|
830
|
-
| Name | Type | Required | Notes |
|
|
831
|
-
| --------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
832
|
-
| `perPage` | integer | No | How many results to return per page. Must be between 10 and 50. Defaults to 20 if omitted. |
|
|
833
|
-
| `cursor` | string | No | A cursor, to return a specific page of results. Cursors can be found from the `pagination.nextCursor` value in each response. |
|
|
834
|
-
|
|
835
|
-
#### Example
|
|
836
|
-
|
|
837
|
-
```ruby
|
|
838
|
-
response = LoopsSdk::Transactional.list
|
|
839
|
-
|
|
840
|
-
response = LoopsSdk::Transactional.list(perPage: 15)
|
|
841
|
-
```
|
|
842
|
-
|
|
843
|
-
#### Response
|
|
844
|
-
|
|
845
|
-
```json
|
|
846
|
-
{
|
|
847
|
-
"pagination": {
|
|
848
|
-
"totalResults": 23,
|
|
849
|
-
"returnedResults": 20,
|
|
850
|
-
"perPage": 20,
|
|
851
|
-
"totalPages": 2,
|
|
852
|
-
"nextCursor": "clyo0q4wo01p59fsecyxqsh38",
|
|
853
|
-
"nextPage": "https://app.loops.so/api/v1/transactional?cursor=clyo0q4wo01p59fsecyxqsh38&perPage=20"
|
|
854
|
-
},
|
|
855
|
-
"data": [
|
|
856
|
-
{
|
|
857
|
-
"id": "clfn0k1yg001imo0fdeqg30i8",
|
|
858
|
-
"lastUpdated": "2023-11-06T17:48:07.249Z",
|
|
859
|
-
"dataVariables": []
|
|
860
|
-
},
|
|
861
|
-
{
|
|
862
|
-
"id": "cll42l54f20i1la0lfooe3z12",
|
|
863
|
-
"lastUpdated": "2025-02-02T02:56:28.845Z",
|
|
864
|
-
"dataVariables": [
|
|
865
|
-
"confirmationUrl"
|
|
866
|
-
]
|
|
867
|
-
},
|
|
868
|
-
{
|
|
869
|
-
"id": "clw6rbuwp01rmeiyndm80155l",
|
|
870
|
-
"lastUpdated": "2024-05-14T19:02:52.000Z",
|
|
871
|
-
"dataVariables": [
|
|
872
|
-
"firstName",
|
|
873
|
-
"lastName",
|
|
874
|
-
"inviteLink"
|
|
875
|
-
]
|
|
876
|
-
},
|
|
877
|
-
...
|
|
878
|
-
]
|
|
879
|
-
}
|
|
880
|
-
```
|
|
881
|
-
|
|
882
|
-
---
|
|
883
|
-
|
|
884
1016
|
### DedicatedSendingIps.list()
|
|
885
1017
|
|
|
886
1018
|
Get Loops' dedicated sending IP addresses.
|
|
@@ -940,12 +1072,12 @@ Get a single theme by ID.
|
|
|
940
1072
|
|
|
941
1073
|
| Name | Type | Required | Notes |
|
|
942
1074
|
| ---------- | ------ | -------- | ----- |
|
|
943
|
-
| `theme_id`
|
|
1075
|
+
| `theme_id` | string | Yes | |
|
|
944
1076
|
|
|
945
1077
|
#### Example
|
|
946
1078
|
|
|
947
1079
|
```ruby
|
|
948
|
-
response = LoopsSdk::Themes.get(theme_id: "
|
|
1080
|
+
response = LoopsSdk::Themes.get(theme_id: "clo5p8q0r0132ntx6flkunw89")
|
|
949
1081
|
```
|
|
950
1082
|
|
|
951
1083
|
---
|
|
@@ -981,12 +1113,12 @@ Get a single component by ID.
|
|
|
981
1113
|
|
|
982
1114
|
| Name | Type | Required | Notes |
|
|
983
1115
|
| -------------- | ------ | -------- | ----- |
|
|
984
|
-
| `component_id`
|
|
1116
|
+
| `component_id` | string | Yes | |
|
|
985
1117
|
|
|
986
1118
|
#### Example
|
|
987
1119
|
|
|
988
1120
|
```ruby
|
|
989
|
-
response = LoopsSdk::Components.get(component_id: "
|
|
1121
|
+
response = LoopsSdk::Components.get(component_id: "clp6q9r1s0154ouy7gmlovx90")
|
|
990
1122
|
```
|
|
991
1123
|
|
|
992
1124
|
---
|
|
@@ -1020,14 +1152,25 @@ Create a draft campaign. An empty email message is created automatically.
|
|
|
1020
1152
|
|
|
1021
1153
|
#### Parameters
|
|
1022
1154
|
|
|
1023
|
-
| Name
|
|
1024
|
-
|
|
|
1025
|
-
| `name`
|
|
1155
|
+
| Name | Type | Required | Notes |
|
|
1156
|
+
| ---------------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------- |
|
|
1157
|
+
| `name` | string | Yes | |
|
|
1158
|
+
| `campaign_group_id` | string | No | The ID of the group to add this campaign to. |
|
|
1159
|
+
| `mailing_list_id` | string | No | The ID of the mailing list to send to. |
|
|
1160
|
+
| `audience_segment_id` | string | No | The ID of an audience segment. Setting this clears any `audience_filter`. |
|
|
1161
|
+
| `audience_filter` | object | No | A tree of audience conditions. See the API reference for the filter schema. |
|
|
1162
|
+
| `scheduling` | object | No | When the campaign should send. Use `{ method: "now" }` or `{ method: "schedule", timestamp: "..." }`. |
|
|
1026
1163
|
|
|
1027
1164
|
#### Example
|
|
1028
1165
|
|
|
1029
1166
|
```ruby
|
|
1030
1167
|
response = LoopsSdk::Campaigns.create(name: "Spring announcement")
|
|
1168
|
+
|
|
1169
|
+
response = LoopsSdk::Campaigns.create(
|
|
1170
|
+
name: "Spring announcement",
|
|
1171
|
+
mailing_list_id: "cm06f5v0e45nf0ml5754o9cix",
|
|
1172
|
+
scheduling: { method: "schedule", timestamp: "2026-06-01T10:00:00Z" }
|
|
1173
|
+
)
|
|
1031
1174
|
```
|
|
1032
1175
|
|
|
1033
1176
|
---
|
|
@@ -1042,34 +1185,41 @@ Get a single campaign by ID.
|
|
|
1042
1185
|
|
|
1043
1186
|
| Name | Type | Required | Notes |
|
|
1044
1187
|
| ------------- | ------ | -------- | ----- |
|
|
1045
|
-
| `campaign_id`
|
|
1188
|
+
| `campaign_id` | string | Yes | |
|
|
1046
1189
|
|
|
1047
1190
|
#### Example
|
|
1048
1191
|
|
|
1049
1192
|
```ruby
|
|
1050
|
-
response = LoopsSdk::Campaigns.get(campaign_id: "
|
|
1193
|
+
response = LoopsSdk::Campaigns.get(campaign_id: "cln4o7p9q0110msw5ekjtmv78")
|
|
1051
1194
|
```
|
|
1052
1195
|
|
|
1053
1196
|
---
|
|
1054
1197
|
|
|
1055
1198
|
### Campaigns.update()
|
|
1056
1199
|
|
|
1057
|
-
Update a draft campaign's name.
|
|
1200
|
+
Update a draft campaign's name, group, audience, or scheduling.
|
|
1058
1201
|
|
|
1059
1202
|
[API Reference](https://loops.so/docs/api-reference/update-campaign)
|
|
1060
1203
|
|
|
1061
1204
|
#### Parameters
|
|
1062
1205
|
|
|
1063
|
-
| Name
|
|
1064
|
-
|
|
|
1065
|
-
| `campaign_id`
|
|
1066
|
-
| `name`
|
|
1206
|
+
| Name | Type | Required | Notes |
|
|
1207
|
+
| --------------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------- |
|
|
1208
|
+
| `campaign_id` | string | Yes | |
|
|
1209
|
+
| `name` | string | No | |
|
|
1210
|
+
| `campaign_group_id` | string | No | The ID of the group to move this campaign to. |
|
|
1211
|
+
| `mailing_list_id` | string | No | The ID of the mailing list to send to. |
|
|
1212
|
+
| `audience_segment_id` | string | No | The ID of an audience segment. Setting this clears any `audience_filter`. |
|
|
1213
|
+
| `audience_filter` | object | No | A tree of audience conditions. See the API reference for the filter schema. |
|
|
1214
|
+
| `scheduling` | object | No | When the campaign should send. Use `{ method: "now" }` or `{ method: "schedule", timestamp: "..." }`. |
|
|
1215
|
+
|
|
1216
|
+
At least one field must be provided.
|
|
1067
1217
|
|
|
1068
1218
|
#### Example
|
|
1069
1219
|
|
|
1070
1220
|
```ruby
|
|
1071
1221
|
response = LoopsSdk::Campaigns.update(
|
|
1072
|
-
campaign_id: "
|
|
1222
|
+
campaign_id: "cln4o7p9q0110msw5ekjtmv78",
|
|
1073
1223
|
name: "Updated campaign name"
|
|
1074
1224
|
)
|
|
1075
1225
|
```
|
|
@@ -1086,12 +1236,12 @@ Get an email message, including its LMX content.
|
|
|
1086
1236
|
|
|
1087
1237
|
| Name | Type | Required | Notes |
|
|
1088
1238
|
| ------------------- | ------ | -------- | ----- |
|
|
1089
|
-
| `email_message_id`
|
|
1239
|
+
| `email_message_id` | string | Yes | |
|
|
1090
1240
|
|
|
1091
1241
|
#### Example
|
|
1092
1242
|
|
|
1093
1243
|
```ruby
|
|
1094
|
-
response = LoopsSdk::EmailMessages.get(email_message_id: "
|
|
1244
|
+
response = LoopsSdk::EmailMessages.get(email_message_id: "cly8k3m0n0044jpx2bghepq45")
|
|
1095
1245
|
```
|
|
1096
1246
|
|
|
1097
1247
|
---
|
|
@@ -1104,23 +1254,30 @@ Update an email message for a draft campaign.
|
|
|
1104
1254
|
|
|
1105
1255
|
#### Parameters
|
|
1106
1256
|
|
|
1107
|
-
| Name
|
|
1108
|
-
|
|
|
1109
|
-
| `email_message_id`
|
|
1110
|
-
| `expected_revision_id`
|
|
1111
|
-
| `subject`
|
|
1112
|
-
| `preview_text`
|
|
1113
|
-
| `from_name`
|
|
1114
|
-
| `from_email`
|
|
1115
|
-
| `reply_to_email`
|
|
1116
|
-
| `
|
|
1257
|
+
| Name | Type | Required | Notes |
|
|
1258
|
+
| ------------------------------ | ------ | -------- | ---------------------------------------------------------------------------------------------------------- |
|
|
1259
|
+
| `email_message_id` | string | Yes | |
|
|
1260
|
+
| `expected_revision_id` | string | No | The `contentRevisionId` from your last fetch. Required to avoid stale concurrent updates. |
|
|
1261
|
+
| `subject` | string | No | |
|
|
1262
|
+
| `preview_text` | string | No | |
|
|
1263
|
+
| `from_name` | string | No | |
|
|
1264
|
+
| `from_email` | string | No | Sender username without `@` or domain. The team's sending domain is appended automatically. |
|
|
1265
|
+
| `reply_to_email` | string | No | Must be empty or a valid email address. |
|
|
1266
|
+
| `cc_email` | string | No | CC email address. Requires the team to have CC/BCC enabled. |
|
|
1267
|
+
| `bcc_email` | string | No | BCC email address. Requires the team to have CC/BCC enabled. |
|
|
1268
|
+
| `language_code` | string | No | Language code for the email. Requires translation to be enabled for the team. |
|
|
1269
|
+
| `email_format` | string | No | The rendering format of the email. One of `styled` or `plain`. |
|
|
1270
|
+
| `lmx` | string | No | Email body serialized as LMX. Styles must be embedded in the LMX `<Style />` tag. |
|
|
1271
|
+
| `contact_properties_fallbacks` | object | No | Fallback values for contact properties. A null value deletes the fallback. |
|
|
1272
|
+
| `event_properties_fallbacks` | object | No | Fallback values for event properties. A null value deletes the fallback. |
|
|
1273
|
+
| `data_variables_fallbacks` | object | No | Fallback values for data variables. A null value deletes the fallback. |
|
|
1117
1274
|
|
|
1118
1275
|
#### Example
|
|
1119
1276
|
|
|
1120
1277
|
```ruby
|
|
1121
1278
|
response = LoopsSdk::EmailMessages.update(
|
|
1122
|
-
email_message_id: "
|
|
1123
|
-
expected_revision_id: "
|
|
1279
|
+
email_message_id: "cly8k3m0n0044jpx2bghepq45",
|
|
1280
|
+
expected_revision_id: "clm9n4o6p0088lrz4dijslt67",
|
|
1124
1281
|
subject: "Spring announcement",
|
|
1125
1282
|
preview_text: "See what's new",
|
|
1126
1283
|
from_name: "Loops",
|
|
@@ -1131,6 +1288,350 @@ response = LoopsSdk::EmailMessages.update(
|
|
|
1131
1288
|
|
|
1132
1289
|
---
|
|
1133
1290
|
|
|
1291
|
+
### EmailMessages.preview()
|
|
1292
|
+
|
|
1293
|
+
Send a test preview of an email message to one or more addresses.
|
|
1294
|
+
|
|
1295
|
+
[API Reference](https://loops.so/docs/api-reference/preview-email-message)
|
|
1296
|
+
|
|
1297
|
+
#### Parameters
|
|
1298
|
+
|
|
1299
|
+
| Name | Type | Required | Notes |
|
|
1300
|
+
| -------------------- | -------- | -------- | --------------------------------------------------------------------------------- |
|
|
1301
|
+
| `email_message_id` | string | Yes | |
|
|
1302
|
+
| `emails` | string[] | Yes | One or more addresses to send the preview to. |
|
|
1303
|
+
| `contact_properties` | object | No | Contact property values to render. Accepted for campaign and workflow previews. |
|
|
1304
|
+
| `event_properties` | object | No | Event property values to render. Accepted for workflow previews only. |
|
|
1305
|
+
| `data_variables` | object | No | Transactional data variables to render. Accepted for transactional previews only. |
|
|
1306
|
+
|
|
1307
|
+
#### Example
|
|
1308
|
+
|
|
1309
|
+
```ruby
|
|
1310
|
+
response = LoopsSdk::EmailMessages.preview(
|
|
1311
|
+
email_message_id: "cly8k3m0n0044jpx2bghepq45",
|
|
1312
|
+
emails: ["test@example.com"],
|
|
1313
|
+
contact_properties: { firstName: "Alex" }
|
|
1314
|
+
)
|
|
1315
|
+
```
|
|
1316
|
+
|
|
1317
|
+
---
|
|
1318
|
+
|
|
1319
|
+
### CampaignGroups.list()
|
|
1320
|
+
|
|
1321
|
+
List campaign groups.
|
|
1322
|
+
|
|
1323
|
+
[API Reference](https://loops.so/docs/api-reference/list-campaign-groups)
|
|
1324
|
+
|
|
1325
|
+
#### Parameters
|
|
1326
|
+
|
|
1327
|
+
| Name | Type | Required | Notes |
|
|
1328
|
+
| --------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
1329
|
+
| `perPage` | integer | No | How many results to return per page. Must be between 10 and 50. Defaults to 20 if omitted. |
|
|
1330
|
+
| `cursor` | string | No | A cursor, to return a specific page of results. Cursors can be found from the `pagination.nextCursor` value in each response. |
|
|
1331
|
+
|
|
1332
|
+
#### Example
|
|
1333
|
+
|
|
1334
|
+
```ruby
|
|
1335
|
+
response = LoopsSdk::CampaignGroups.list
|
|
1336
|
+
```
|
|
1337
|
+
|
|
1338
|
+
---
|
|
1339
|
+
|
|
1340
|
+
### CampaignGroups.create()
|
|
1341
|
+
|
|
1342
|
+
Create a campaign group.
|
|
1343
|
+
|
|
1344
|
+
[API Reference](https://loops.so/docs/api-reference/create-campaign-group)
|
|
1345
|
+
|
|
1346
|
+
#### Parameters
|
|
1347
|
+
|
|
1348
|
+
| Name | Type | Required | Notes |
|
|
1349
|
+
| ------------- | ------ | -------- | --------------------------------------- |
|
|
1350
|
+
| `name` | string | Yes | Cannot be the reserved name "Unsorted". |
|
|
1351
|
+
| `description` | string | No | An optional description for the group. |
|
|
1352
|
+
|
|
1353
|
+
#### Example
|
|
1354
|
+
|
|
1355
|
+
```ruby
|
|
1356
|
+
response = LoopsSdk::CampaignGroups.create(name: "Newsletters", description: "Monthly updates")
|
|
1357
|
+
```
|
|
1358
|
+
|
|
1359
|
+
---
|
|
1360
|
+
|
|
1361
|
+
### CampaignGroups.get()
|
|
1362
|
+
|
|
1363
|
+
Get a campaign group by ID.
|
|
1364
|
+
|
|
1365
|
+
[API Reference](https://loops.so/docs/api-reference/get-campaign-group)
|
|
1366
|
+
|
|
1367
|
+
#### Parameters
|
|
1368
|
+
|
|
1369
|
+
| Name | Type | Required | Notes |
|
|
1370
|
+
| ---- | ------ | -------- | ----- |
|
|
1371
|
+
| `campaign_group_id` | string | Yes | |
|
|
1372
|
+
|
|
1373
|
+
#### Example
|
|
1374
|
+
|
|
1375
|
+
```ruby
|
|
1376
|
+
response = LoopsSdk::CampaignGroups.get(campaign_group_id: "clq7r0s2t0176pvz8hnmpwy01")
|
|
1377
|
+
```
|
|
1378
|
+
|
|
1379
|
+
---
|
|
1380
|
+
|
|
1381
|
+
### CampaignGroups.update()
|
|
1382
|
+
|
|
1383
|
+
Update a campaign group's name or description.
|
|
1384
|
+
|
|
1385
|
+
[API Reference](https://loops.so/docs/api-reference/update-campaign-group)
|
|
1386
|
+
|
|
1387
|
+
#### Parameters
|
|
1388
|
+
|
|
1389
|
+
| Name | Type | Required | Notes |
|
|
1390
|
+
| ------------- | ------ | -------- | --------------------------------------- |
|
|
1391
|
+
| `campaign_group_id` | string | Yes | |
|
|
1392
|
+
| `name` | string | No | Cannot be the reserved name "Unsorted". |
|
|
1393
|
+
| `description` | string | No | |
|
|
1394
|
+
|
|
1395
|
+
At least one field must be provided.
|
|
1396
|
+
|
|
1397
|
+
#### Example
|
|
1398
|
+
|
|
1399
|
+
```ruby
|
|
1400
|
+
response = LoopsSdk::CampaignGroups.update(
|
|
1401
|
+
campaign_group_id: "clq7r0s2t0176pvz8hnmpwy01",
|
|
1402
|
+
name: "Updated name"
|
|
1403
|
+
)
|
|
1404
|
+
```
|
|
1405
|
+
|
|
1406
|
+
---
|
|
1407
|
+
|
|
1408
|
+
### AudienceSegments.list()
|
|
1409
|
+
|
|
1410
|
+
List audience segments.
|
|
1411
|
+
|
|
1412
|
+
[API Reference](https://loops.so/docs/api-reference/list-audience-segments)
|
|
1413
|
+
|
|
1414
|
+
#### Parameters
|
|
1415
|
+
|
|
1416
|
+
| Name | Type | Required | Notes |
|
|
1417
|
+
| --------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
1418
|
+
| `perPage` | integer | No | How many results to return per page. Must be between 10 and 50. Defaults to 20 if omitted. |
|
|
1419
|
+
| `cursor` | string | No | A cursor, to return a specific page of results. Cursors can be found from the `pagination.nextCursor` value in each response. |
|
|
1420
|
+
|
|
1421
|
+
#### Example
|
|
1422
|
+
|
|
1423
|
+
```ruby
|
|
1424
|
+
response = LoopsSdk::AudienceSegments.list
|
|
1425
|
+
```
|
|
1426
|
+
|
|
1427
|
+
---
|
|
1428
|
+
|
|
1429
|
+
### AudienceSegments.get()
|
|
1430
|
+
|
|
1431
|
+
Get an audience segment by ID.
|
|
1432
|
+
|
|
1433
|
+
[API Reference](https://loops.so/docs/api-reference/get-audience-segment)
|
|
1434
|
+
|
|
1435
|
+
#### Parameters
|
|
1436
|
+
|
|
1437
|
+
| Name | Type | Required | Notes |
|
|
1438
|
+
| ---- | ------ | -------- | ----- |
|
|
1439
|
+
| `audience_segment_id` | string | Yes | |
|
|
1440
|
+
|
|
1441
|
+
#### Example
|
|
1442
|
+
|
|
1443
|
+
```ruby
|
|
1444
|
+
response = LoopsSdk::AudienceSegments.get(audience_segment_id: "clr8s1t3u0198qw09iotqzx12")
|
|
1445
|
+
```
|
|
1446
|
+
|
|
1447
|
+
---
|
|
1448
|
+
|
|
1449
|
+
### Workflows.list()
|
|
1450
|
+
|
|
1451
|
+
List workflows.
|
|
1452
|
+
|
|
1453
|
+
[API Reference](https://loops.so/docs/api-reference/list-workflows)
|
|
1454
|
+
|
|
1455
|
+
#### Parameters
|
|
1456
|
+
|
|
1457
|
+
| Name | Type | Required | Notes |
|
|
1458
|
+
| --------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
1459
|
+
| `perPage` | integer | No | How many results to return per page. Must be between 10 and 50. Defaults to 20 if omitted. |
|
|
1460
|
+
| `cursor` | string | No | A cursor, to return a specific page of results. Cursors can be found from the `pagination.nextCursor` value in each response. |
|
|
1461
|
+
|
|
1462
|
+
#### Example
|
|
1463
|
+
|
|
1464
|
+
```ruby
|
|
1465
|
+
response = LoopsSdk::Workflows.list
|
|
1466
|
+
```
|
|
1467
|
+
|
|
1468
|
+
---
|
|
1469
|
+
|
|
1470
|
+
### Workflows.get()
|
|
1471
|
+
|
|
1472
|
+
Get a simplified workflow graph.
|
|
1473
|
+
|
|
1474
|
+
[API Reference](https://loops.so/docs/api-reference/get-workflow)
|
|
1475
|
+
|
|
1476
|
+
#### Parameters
|
|
1477
|
+
|
|
1478
|
+
| Name | Type | Required | Notes |
|
|
1479
|
+
| ---- | ------ | -------- | ----- |
|
|
1480
|
+
| `workflow_id` | string | Yes | |
|
|
1481
|
+
|
|
1482
|
+
#### Example
|
|
1483
|
+
|
|
1484
|
+
```ruby
|
|
1485
|
+
response = LoopsSdk::Workflows.get(workflow_id: "cls9t2u4v0210rx20jpuary23")
|
|
1486
|
+
```
|
|
1487
|
+
|
|
1488
|
+
---
|
|
1489
|
+
|
|
1490
|
+
### Workflows.get_node()
|
|
1491
|
+
|
|
1492
|
+
Get detailed data for a single workflow node.
|
|
1493
|
+
|
|
1494
|
+
[API Reference](https://loops.so/docs/api-reference/get-workflow-node)
|
|
1495
|
+
|
|
1496
|
+
#### Parameters
|
|
1497
|
+
|
|
1498
|
+
| Name | Type | Required | Notes |
|
|
1499
|
+
| ------------ | ------ | -------- | ----- |
|
|
1500
|
+
| `workflow_id`| string | Yes | |
|
|
1501
|
+
| `node_id` | string | Yes | |
|
|
1502
|
+
|
|
1503
|
+
#### Example
|
|
1504
|
+
|
|
1505
|
+
```ruby
|
|
1506
|
+
response = LoopsSdk::Workflows.get_node(workflow_id: "cls9t2u4v0210rx20jpuary23", node_id: "clt0u3v5w0232sy31kqvbzs34")
|
|
1507
|
+
```
|
|
1508
|
+
|
|
1509
|
+
---
|
|
1510
|
+
|
|
1511
|
+
### TransactionalGroups.list()
|
|
1512
|
+
|
|
1513
|
+
List transactional groups.
|
|
1514
|
+
|
|
1515
|
+
[API Reference](https://loops.so/docs/api-reference/list-transactional-groups)
|
|
1516
|
+
|
|
1517
|
+
#### Parameters
|
|
1518
|
+
|
|
1519
|
+
| Name | Type | Required | Notes |
|
|
1520
|
+
| --------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
1521
|
+
| `perPage` | integer | No | How many results to return per page. Must be between 10 and 50. Defaults to 20 if omitted. |
|
|
1522
|
+
| `cursor` | string | No | A cursor, to return a specific page of results. Cursors can be found from the `pagination.nextCursor` value in each response. |
|
|
1523
|
+
|
|
1524
|
+
#### Example
|
|
1525
|
+
|
|
1526
|
+
```ruby
|
|
1527
|
+
response = LoopsSdk::TransactionalGroups.list
|
|
1528
|
+
```
|
|
1529
|
+
|
|
1530
|
+
---
|
|
1531
|
+
|
|
1532
|
+
### TransactionalGroups.create()
|
|
1533
|
+
|
|
1534
|
+
Create a transactional group.
|
|
1535
|
+
|
|
1536
|
+
[API Reference](https://loops.so/docs/api-reference/create-transactional-group)
|
|
1537
|
+
|
|
1538
|
+
#### Parameters
|
|
1539
|
+
|
|
1540
|
+
| Name | Type | Required | Notes |
|
|
1541
|
+
| ------------- | ------ | -------- | --------------------------------------- |
|
|
1542
|
+
| `name` | string | Yes | Cannot be the reserved name "Unsorted". |
|
|
1543
|
+
| `description` | string | No | An optional description for the group. |
|
|
1544
|
+
|
|
1545
|
+
#### Example
|
|
1546
|
+
|
|
1547
|
+
```ruby
|
|
1548
|
+
response = LoopsSdk::TransactionalGroups.create(name: "Account emails")
|
|
1549
|
+
```
|
|
1550
|
+
|
|
1551
|
+
---
|
|
1552
|
+
|
|
1553
|
+
### TransactionalGroups.get()
|
|
1554
|
+
|
|
1555
|
+
Get a transactional group by ID.
|
|
1556
|
+
|
|
1557
|
+
[API Reference](https://loops.so/docs/api-reference/get-transactional-group)
|
|
1558
|
+
|
|
1559
|
+
#### Parameters
|
|
1560
|
+
|
|
1561
|
+
| Name | Type | Required | Notes |
|
|
1562
|
+
| ---- | ------ | -------- | ----- |
|
|
1563
|
+
| `transactional_group_id` | string | Yes | |
|
|
1564
|
+
|
|
1565
|
+
#### Example
|
|
1566
|
+
|
|
1567
|
+
```ruby
|
|
1568
|
+
response = LoopsSdk::TransactionalGroups.get(transactional_group_id: "clv2w3x4y0288xbb0kqrsuv67")
|
|
1569
|
+
```
|
|
1570
|
+
|
|
1571
|
+
---
|
|
1572
|
+
|
|
1573
|
+
### TransactionalGroups.update()
|
|
1574
|
+
|
|
1575
|
+
Update a transactional group's name or description.
|
|
1576
|
+
|
|
1577
|
+
[API Reference](https://loops.so/docs/api-reference/update-transactional-group)
|
|
1578
|
+
|
|
1579
|
+
#### Parameters
|
|
1580
|
+
|
|
1581
|
+
| Name | Type | Required | Notes |
|
|
1582
|
+
| ------------- | ------ | -------- | --------------------------------------- |
|
|
1583
|
+
| `transactional_group_id` | string | Yes | |
|
|
1584
|
+
| `name` | string | No | Cannot be the reserved name "Unsorted". |
|
|
1585
|
+
| `description` | string | No | |
|
|
1586
|
+
|
|
1587
|
+
At least one field must be provided.
|
|
1588
|
+
|
|
1589
|
+
#### Example
|
|
1590
|
+
|
|
1591
|
+
```ruby
|
|
1592
|
+
response = LoopsSdk::TransactionalGroups.update(
|
|
1593
|
+
transactional_group_id: "clv2w3x4y0288xbb0kqrsuv67",
|
|
1594
|
+
name: "Updated name"
|
|
1595
|
+
)
|
|
1596
|
+
```
|
|
1597
|
+
|
|
1598
|
+
---
|
|
1599
|
+
|
|
1600
|
+
### Uploads.upload()
|
|
1601
|
+
|
|
1602
|
+
Upload an image file for use in LMX email content.
|
|
1603
|
+
|
|
1604
|
+
Supported image types: JPEG, PNG, GIF, and WebP (max 4 MB). MIME type is detected from file contents, or pass `content_type:` to override.
|
|
1605
|
+
|
|
1606
|
+
[API Reference](https://loops.so/docs/api-reference/create-upload)
|
|
1607
|
+
|
|
1608
|
+
#### Parameters
|
|
1609
|
+
|
|
1610
|
+
| Name | Type | Required | Notes |
|
|
1611
|
+
| --------------- | ------ | -------- | -------------------------------------------------------------------------------------------- |
|
|
1612
|
+
| `path` | string | Yes | Path to the image file on disk. |
|
|
1613
|
+
| `content_type` | string | No | MIME type override. Supported: `image/jpeg`, `image/png`, `image/gif`, `image/webp`. |
|
|
1614
|
+
|
|
1615
|
+
#### Example
|
|
1616
|
+
|
|
1617
|
+
```ruby
|
|
1618
|
+
response = LoopsSdk::Uploads.upload(path: "./header.png")
|
|
1619
|
+
|
|
1620
|
+
# Use the returned URL in LMX
|
|
1621
|
+
lmx = %(<Image src="#{response['finalUrl']}" alt="Header" />)
|
|
1622
|
+
```
|
|
1623
|
+
|
|
1624
|
+
#### Response
|
|
1625
|
+
|
|
1626
|
+
```json
|
|
1627
|
+
{
|
|
1628
|
+
"emailAssetId": "clu1v4w6x0254tz42lrcwat45",
|
|
1629
|
+
"finalUrl": "https://cdn.loops.so/clu1v4w6x0254tz42lrcwat45.png"
|
|
1630
|
+
}
|
|
1631
|
+
```
|
|
1632
|
+
|
|
1633
|
+
---
|
|
1634
|
+
|
|
1134
1635
|
## Testing
|
|
1135
1636
|
|
|
1136
1637
|
Run tests with `bundle exec rspec`.
|
|
@@ -1139,4 +1640,4 @@ Run tests with `bundle exec rspec`.
|
|
|
1139
1640
|
|
|
1140
1641
|
## Contributing
|
|
1141
1642
|
|
|
1142
|
-
Bug reports and pull requests are welcome. Please read our [Contributing Guidelines](CONTRIBUTING.md).
|
|
1643
|
+
Bug reports and pull requests are welcome. Please read our [Contributing Guidelines](CONTRIBUTING.md).
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LoopsSdk
|
|
4
|
+
class AudienceSegments < Base
|
|
5
|
+
class << self
|
|
6
|
+
def list(perPage: 20, cursor: nil)
|
|
7
|
+
make_request(method: :get, path: "v1/audience-segments", params: { perPage: perPage, cursor: cursor })
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def get(audience_segment_id:)
|
|
11
|
+
make_request(method: :get, path: "v1/audience-segments/#{audience_segment_id}")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LoopsSdk
|
|
4
|
+
class CampaignGroups < Base
|
|
5
|
+
class << self
|
|
6
|
+
def list(perPage: 20, cursor: nil)
|
|
7
|
+
make_request(method: :get, path: "v1/campaign-groups", params: { perPage: perPage, cursor: cursor })
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def create(name:, description: nil)
|
|
11
|
+
body = { name: name, description: description }.compact
|
|
12
|
+
make_request(method: :post, path: "v1/campaign-groups", body: body)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def get(campaign_group_id:)
|
|
16
|
+
make_request(method: :get, path: "v1/campaign-groups/#{campaign_group_id}")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def update(campaign_group_id:, name: nil, description: nil)
|
|
20
|
+
body = { name: name, description: description }.compact
|
|
21
|
+
make_request(method: :post, path: "v1/campaign-groups/#{campaign_group_id}", body: body)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/loops_sdk/campaigns.rb
CHANGED
|
@@ -7,16 +7,32 @@ module LoopsSdk
|
|
|
7
7
|
make_request(method: :get, path: "v1/campaigns", params: { perPage: perPage, cursor: cursor })
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
def create(name:)
|
|
11
|
-
|
|
10
|
+
def create(name:, campaign_group_id: nil, mailing_list_id: nil, audience_segment_id: nil, audience_filter: nil, scheduling: nil)
|
|
11
|
+
body = {
|
|
12
|
+
name: name,
|
|
13
|
+
campaignGroupId: campaign_group_id,
|
|
14
|
+
mailingListId: mailing_list_id,
|
|
15
|
+
audienceSegmentId: audience_segment_id,
|
|
16
|
+
audienceFilter: audience_filter,
|
|
17
|
+
scheduling: scheduling
|
|
18
|
+
}.compact
|
|
19
|
+
make_request(method: :post, path: "v1/campaigns", body: body)
|
|
12
20
|
end
|
|
13
21
|
|
|
14
22
|
def get(campaign_id:)
|
|
15
23
|
make_request(method: :get, path: "v1/campaigns/#{campaign_id}")
|
|
16
24
|
end
|
|
17
25
|
|
|
18
|
-
def update(campaign_id:, name:)
|
|
19
|
-
|
|
26
|
+
def update(campaign_id:, name: nil, campaign_group_id: nil, mailing_list_id: nil, audience_segment_id: nil, audience_filter: nil, scheduling: nil)
|
|
27
|
+
body = {
|
|
28
|
+
name: name,
|
|
29
|
+
campaignGroupId: campaign_group_id,
|
|
30
|
+
mailingListId: mailing_list_id,
|
|
31
|
+
audienceSegmentId: audience_segment_id,
|
|
32
|
+
audienceFilter: audience_filter,
|
|
33
|
+
scheduling: scheduling
|
|
34
|
+
}.compact
|
|
35
|
+
make_request(method: :post, path: "v1/campaigns/#{campaign_id}", body: body)
|
|
20
36
|
end
|
|
21
37
|
end
|
|
22
38
|
end
|
|
@@ -7,7 +7,23 @@ module LoopsSdk
|
|
|
7
7
|
make_request(method: :get, path: "v1/email-messages/#{email_message_id}")
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
def update(
|
|
10
|
+
def update(
|
|
11
|
+
email_message_id:,
|
|
12
|
+
expected_revision_id: nil,
|
|
13
|
+
subject: nil,
|
|
14
|
+
preview_text: nil,
|
|
15
|
+
from_name: nil,
|
|
16
|
+
from_email: nil,
|
|
17
|
+
reply_to_email: nil,
|
|
18
|
+
cc_email: nil,
|
|
19
|
+
bcc_email: nil,
|
|
20
|
+
language_code: nil,
|
|
21
|
+
email_format: nil,
|
|
22
|
+
lmx: nil,
|
|
23
|
+
contact_properties_fallbacks: nil,
|
|
24
|
+
event_properties_fallbacks: nil,
|
|
25
|
+
data_variables_fallbacks: nil
|
|
26
|
+
)
|
|
11
27
|
body = {
|
|
12
28
|
expectedRevisionId: expected_revision_id,
|
|
13
29
|
subject: subject,
|
|
@@ -15,10 +31,27 @@ module LoopsSdk
|
|
|
15
31
|
fromName: from_name,
|
|
16
32
|
fromEmail: from_email,
|
|
17
33
|
replyToEmail: reply_to_email,
|
|
18
|
-
|
|
34
|
+
ccEmail: cc_email,
|
|
35
|
+
bccEmail: bcc_email,
|
|
36
|
+
languageCode: language_code,
|
|
37
|
+
emailFormat: email_format,
|
|
38
|
+
lmx: lmx,
|
|
39
|
+
contactPropertiesFallbacks: contact_properties_fallbacks,
|
|
40
|
+
eventPropertiesFallbacks: event_properties_fallbacks,
|
|
41
|
+
dataVariablesFallbacks: data_variables_fallbacks
|
|
19
42
|
}.compact
|
|
20
43
|
make_request(method: :post, path: "v1/email-messages/#{email_message_id}", body: body)
|
|
21
44
|
end
|
|
45
|
+
|
|
46
|
+
def preview(email_message_id:, emails:, contact_properties: nil, event_properties: nil, data_variables: nil)
|
|
47
|
+
body = {
|
|
48
|
+
emails: emails,
|
|
49
|
+
contactProperties: contact_properties,
|
|
50
|
+
eventProperties: event_properties,
|
|
51
|
+
dataVariables: data_variables
|
|
52
|
+
}.compact
|
|
53
|
+
make_request(method: :post, path: "v1/email-messages/#{email_message_id}/preview", body: body)
|
|
54
|
+
end
|
|
22
55
|
end
|
|
23
56
|
end
|
|
24
57
|
end
|
|
@@ -4,8 +4,31 @@ module LoopsSdk
|
|
|
4
4
|
class Transactional < Base
|
|
5
5
|
class << self
|
|
6
6
|
def list(perPage: 20, cursor: nil)
|
|
7
|
-
make_request(method: :get, path: "v1/transactional", params: { perPage: perPage, cursor: cursor })
|
|
7
|
+
make_request(method: :get, path: "v1/transactional-emails", params: { perPage: perPage, cursor: cursor })
|
|
8
8
|
end
|
|
9
|
+
|
|
10
|
+
def create(name:, transactional_group_id: nil)
|
|
11
|
+
body = { name: name, transactionalGroupId: transactional_group_id }.compact
|
|
12
|
+
make_request(method: :post, path: "v1/transactional-emails", body: body)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def get(transactional_id:)
|
|
16
|
+
make_request(method: :get, path: "v1/transactional-emails/#{transactional_id}")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def update(transactional_id:, name: nil, transactional_group_id: nil)
|
|
20
|
+
body = { name: name, transactionalGroupId: transactional_group_id }.compact
|
|
21
|
+
make_request(method: :post, path: "v1/transactional-emails/#{transactional_id}", body: body)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def ensure_draft(transactional_id:)
|
|
25
|
+
make_request(method: :post, path: "v1/transactional-emails/#{transactional_id}/draft")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def publish(transactional_id:)
|
|
29
|
+
make_request(method: :post, path: "v1/transactional-emails/#{transactional_id}/publish")
|
|
30
|
+
end
|
|
31
|
+
|
|
9
32
|
def send(transactional_id:, email:, add_to_audience: false, data_variables: {}, attachments: [], headers: {})
|
|
10
33
|
attachments = attachments.map do |attachment|
|
|
11
34
|
attachment.transform_keys { |key| key == :content_type ? :contentType : key }
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LoopsSdk
|
|
4
|
+
class TransactionalGroups < Base
|
|
5
|
+
class << self
|
|
6
|
+
def list(perPage: 20, cursor: nil)
|
|
7
|
+
make_request(method: :get, path: "v1/transactional-groups", params: { perPage: perPage, cursor: cursor })
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def create(name:, description: nil)
|
|
11
|
+
body = { name: name, description: description }.compact
|
|
12
|
+
make_request(method: :post, path: "v1/transactional-groups", body: body)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def get(transactional_group_id:)
|
|
16
|
+
make_request(method: :get, path: "v1/transactional-groups/#{transactional_group_id}")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def update(transactional_group_id:, name: nil, description: nil)
|
|
20
|
+
body = { name: name, description: description }.compact
|
|
21
|
+
make_request(method: :post, path: "v1/transactional-groups/#{transactional_group_id}", body: body)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LoopsSdk
|
|
4
|
+
class Uploads < Base
|
|
5
|
+
SUPPORTED_CONTENT_TYPES = %w[image/jpeg image/png image/gif image/webp].freeze
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
def upload(path:, content_type: nil)
|
|
9
|
+
data = File.binread(path)
|
|
10
|
+
content_type ||= detect_content_type(data)
|
|
11
|
+
validate_content_type!(content_type)
|
|
12
|
+
|
|
13
|
+
create_response = make_request(
|
|
14
|
+
method: :post,
|
|
15
|
+
path: "v1/uploads",
|
|
16
|
+
body: { contentType: content_type, contentLength: data.bytesize }
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
put_to_presigned_url(create_response["presignedUrl"], data, content_type)
|
|
20
|
+
|
|
21
|
+
make_request(
|
|
22
|
+
method: :post,
|
|
23
|
+
path: "v1/uploads/#{create_response["emailAssetId"]}/complete"
|
|
24
|
+
)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def detect_content_type(data)
|
|
30
|
+
if data.start_with?("\xFF\xD8\xFF".b)
|
|
31
|
+
"image/jpeg"
|
|
32
|
+
elsif data.start_with?("\x89PNG\r\n\x1a\n".b)
|
|
33
|
+
"image/png"
|
|
34
|
+
elsif data.start_with?("GIF87a".b, "GIF89a".b)
|
|
35
|
+
"image/gif"
|
|
36
|
+
elsif data.bytesize >= 12 && data[0, 4] == "RIFF".b && data[8, 4] == "WEBP".b
|
|
37
|
+
"image/webp"
|
|
38
|
+
else
|
|
39
|
+
raise ArgumentError,
|
|
40
|
+
"Unable to detect image type. Pass content_type: explicitly. " \
|
|
41
|
+
"Supported types: #{SUPPORTED_CONTENT_TYPES.join(', ')}."
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def validate_content_type!(content_type)
|
|
46
|
+
return if SUPPORTED_CONTENT_TYPES.include?(content_type)
|
|
47
|
+
|
|
48
|
+
raise ArgumentError,
|
|
49
|
+
"Unsupported content_type: #{content_type}. " \
|
|
50
|
+
"Supported types: #{SUPPORTED_CONTENT_TYPES.join(', ')}."
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def put_to_presigned_url(url, data, content_type)
|
|
54
|
+
response = Faraday.put(url) do |req|
|
|
55
|
+
req.headers["Content-Type"] = content_type
|
|
56
|
+
req.headers["Content-Length"] = data.bytesize.to_s
|
|
57
|
+
req.body = data
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
return if response.success?
|
|
61
|
+
|
|
62
|
+
raise APIError.new(response.status, response.body)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
data/lib/loops_sdk/version.rb
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LoopsSdk
|
|
4
|
+
class Workflows < Base
|
|
5
|
+
class << self
|
|
6
|
+
def list(perPage: 20, cursor: nil)
|
|
7
|
+
make_request(method: :get, path: "v1/workflows", params: { perPage: perPage, cursor: cursor })
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def get(workflow_id:)
|
|
11
|
+
make_request(method: :get, path: "v1/workflows/#{workflow_id}")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def get_node(workflow_id:, node_id:)
|
|
15
|
+
make_request(method: :get, path: "v1/workflows/#{workflow_id}/nodes/#{node_id}")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/loops_sdk.rb
CHANGED
|
@@ -15,7 +15,12 @@ require_relative "loops_sdk/dedicated_sending_ips"
|
|
|
15
15
|
require_relative "loops_sdk/themes"
|
|
16
16
|
require_relative "loops_sdk/components"
|
|
17
17
|
require_relative "loops_sdk/campaigns"
|
|
18
|
+
require_relative "loops_sdk/campaign_groups"
|
|
18
19
|
require_relative "loops_sdk/email_messages"
|
|
20
|
+
require_relative "loops_sdk/uploads"
|
|
21
|
+
require_relative "loops_sdk/audience_segments"
|
|
22
|
+
require_relative "loops_sdk/workflows"
|
|
23
|
+
require_relative "loops_sdk/transactional_groups"
|
|
19
24
|
|
|
20
25
|
module LoopsSdk
|
|
21
26
|
class << self
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: loops_sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dan Rowden
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-06-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|
|
@@ -35,7 +35,9 @@ files:
|
|
|
35
35
|
- README.md
|
|
36
36
|
- lib/loops_sdk.rb
|
|
37
37
|
- lib/loops_sdk/api_key.rb
|
|
38
|
+
- lib/loops_sdk/audience_segments.rb
|
|
38
39
|
- lib/loops_sdk/base.rb
|
|
40
|
+
- lib/loops_sdk/campaign_groups.rb
|
|
39
41
|
- lib/loops_sdk/campaigns.rb
|
|
40
42
|
- lib/loops_sdk/components.rb
|
|
41
43
|
- lib/loops_sdk/configuration.rb
|
|
@@ -47,7 +49,10 @@ files:
|
|
|
47
49
|
- lib/loops_sdk/mailing_lists.rb
|
|
48
50
|
- lib/loops_sdk/themes.rb
|
|
49
51
|
- lib/loops_sdk/transactional.rb
|
|
52
|
+
- lib/loops_sdk/transactional_groups.rb
|
|
53
|
+
- lib/loops_sdk/uploads.rb
|
|
50
54
|
- lib/loops_sdk/version.rb
|
|
55
|
+
- lib/loops_sdk/workflows.rb
|
|
51
56
|
homepage: https://loops.so/docs/api-reference
|
|
52
57
|
licenses:
|
|
53
58
|
- MIT
|