loops_sdk 2.1.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 +804 -42
- data/lib/loops_sdk/audience_segments.rb +15 -0
- data/lib/loops_sdk/base.rb +2 -2
- data/lib/loops_sdk/campaign_groups.rb +25 -0
- data/lib/loops_sdk/campaigns.rb +39 -0
- data/lib/loops_sdk/components.rb +15 -0
- data/lib/loops_sdk/dedicated_sending_ips.rb +11 -0
- data/lib/loops_sdk/email_messages.rb +57 -0
- data/lib/loops_sdk/themes.rb +15 -0
- 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 +10 -0
- metadata +12 -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,39 @@ 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)
|
|
124
|
+
- [DedicatedSendingIps.list()](#dedicatedsendingipslist)
|
|
125
|
+
- [Themes.list()](#themeslist)
|
|
126
|
+
- [Themes.get()](#themesget)
|
|
127
|
+
- [Components.list()](#componentslist)
|
|
128
|
+
- [Components.get()](#componentsget)
|
|
129
|
+
- [Campaigns.list()](#campaignslist)
|
|
130
|
+
- [Campaigns.create()](#campaignscreate)
|
|
131
|
+
- [Campaigns.get()](#campaignsget)
|
|
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)
|
|
142
|
+
- [EmailMessages.get()](#emailmessagesget)
|
|
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)
|
|
119
150
|
|
|
120
151
|
---
|
|
121
152
|
|
|
@@ -195,7 +226,7 @@ This method will return a success or error message:
|
|
|
195
226
|
```json
|
|
196
227
|
{
|
|
197
228
|
"success": true,
|
|
198
|
-
"id": "
|
|
229
|
+
"id": "cll6b3i8901a9jx0oyktl2m4u"
|
|
199
230
|
}
|
|
200
231
|
```
|
|
201
232
|
|
|
@@ -259,7 +290,7 @@ This method will return a success or error message:
|
|
|
259
290
|
```json
|
|
260
291
|
{
|
|
261
292
|
"success": true,
|
|
262
|
-
"id": "
|
|
293
|
+
"id": "cll6b3i8901a9jx0oyktl2m4u"
|
|
263
294
|
}
|
|
264
295
|
```
|
|
265
296
|
|
|
@@ -715,6 +746,180 @@ This method will return a success or error:
|
|
|
715
746
|
|
|
716
747
|
---
|
|
717
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
|
+
|
|
718
923
|
### Transactional.send()
|
|
719
924
|
|
|
720
925
|
Send a transactional email to a contact. [Learn about sending transactional email](https://loops.so/docs/transactional/guide)
|
|
@@ -725,7 +930,7 @@ Send a transactional email to a contact. [Learn about sending transactional emai
|
|
|
725
930
|
|
|
726
931
|
| Name | Type | Required | Notes |
|
|
727
932
|
| ---------------------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
728
|
-
| `transactional_id`
|
|
933
|
+
| `transactional_id` | string | Yes | The ID of the transactional email to send. |
|
|
729
934
|
| `email` | string | Yes | The email address of the recipient. |
|
|
730
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). |
|
|
731
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`. |
|
|
@@ -808,11 +1013,37 @@ If there is a problem with the request, a descriptive error message will be retu
|
|
|
808
1013
|
|
|
809
1014
|
---
|
|
810
1015
|
|
|
811
|
-
###
|
|
1016
|
+
### DedicatedSendingIps.list()
|
|
812
1017
|
|
|
813
|
-
Get
|
|
1018
|
+
Get Loops' dedicated sending IP addresses.
|
|
814
1019
|
|
|
815
|
-
[API Reference](https://loops.so/docs/api-reference/list-
|
|
1020
|
+
[API Reference](https://loops.so/docs/api-reference/list-dedicated-sending-ips)
|
|
1021
|
+
|
|
1022
|
+
#### Parameters
|
|
1023
|
+
|
|
1024
|
+
None
|
|
1025
|
+
|
|
1026
|
+
#### Example
|
|
1027
|
+
|
|
1028
|
+
```ruby
|
|
1029
|
+
response = LoopsSdk::DedicatedSendingIps.list
|
|
1030
|
+
```
|
|
1031
|
+
|
|
1032
|
+
#### Response
|
|
1033
|
+
|
|
1034
|
+
Returns an array of IP address strings.
|
|
1035
|
+
|
|
1036
|
+
```json
|
|
1037
|
+
["1.2.3.4", "5.6.7.8"]
|
|
1038
|
+
```
|
|
1039
|
+
|
|
1040
|
+
---
|
|
1041
|
+
|
|
1042
|
+
### Themes.list()
|
|
1043
|
+
|
|
1044
|
+
List email themes.
|
|
1045
|
+
|
|
1046
|
+
[API Reference](https://loops.so/docs/api-reference/list-themes)
|
|
816
1047
|
|
|
817
1048
|
#### Parameters
|
|
818
1049
|
|
|
@@ -824,47 +1055,578 @@ Get a list of published transactional emails.
|
|
|
824
1055
|
#### Example
|
|
825
1056
|
|
|
826
1057
|
```ruby
|
|
827
|
-
response = LoopsSdk::
|
|
1058
|
+
response = LoopsSdk::Themes.list
|
|
1059
|
+
|
|
1060
|
+
response = LoopsSdk::Themes.list(perPage: 15, cursor: "cursor_value")
|
|
1061
|
+
```
|
|
1062
|
+
|
|
1063
|
+
---
|
|
1064
|
+
|
|
1065
|
+
### Themes.get()
|
|
1066
|
+
|
|
1067
|
+
Get a single theme by ID.
|
|
1068
|
+
|
|
1069
|
+
[API Reference](https://loops.so/docs/api-reference/get-theme)
|
|
1070
|
+
|
|
1071
|
+
#### Parameters
|
|
1072
|
+
|
|
1073
|
+
| Name | Type | Required | Notes |
|
|
1074
|
+
| ---------- | ------ | -------- | ----- |
|
|
1075
|
+
| `theme_id` | string | Yes | |
|
|
1076
|
+
|
|
1077
|
+
#### Example
|
|
1078
|
+
|
|
1079
|
+
```ruby
|
|
1080
|
+
response = LoopsSdk::Themes.get(theme_id: "clo5p8q0r0132ntx6flkunw89")
|
|
1081
|
+
```
|
|
1082
|
+
|
|
1083
|
+
---
|
|
1084
|
+
|
|
1085
|
+
### Components.list()
|
|
1086
|
+
|
|
1087
|
+
List email components.
|
|
1088
|
+
|
|
1089
|
+
[API Reference](https://loops.so/docs/api-reference/list-components)
|
|
1090
|
+
|
|
1091
|
+
#### Parameters
|
|
1092
|
+
|
|
1093
|
+
| Name | Type | Required | Notes |
|
|
1094
|
+
| --------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
1095
|
+
| `perPage` | integer | No | How many results to return per page. Must be between 10 and 50. Defaults to 20 if omitted. |
|
|
1096
|
+
| `cursor` | string | No | A cursor, to return a specific page of results. Cursors can be found from the `pagination.nextCursor` value in each response. |
|
|
1097
|
+
|
|
1098
|
+
#### Example
|
|
1099
|
+
|
|
1100
|
+
```ruby
|
|
1101
|
+
response = LoopsSdk::Components.list
|
|
1102
|
+
```
|
|
1103
|
+
|
|
1104
|
+
---
|
|
1105
|
+
|
|
1106
|
+
### Components.get()
|
|
1107
|
+
|
|
1108
|
+
Get a single component by ID.
|
|
1109
|
+
|
|
1110
|
+
[API Reference](https://loops.so/docs/api-reference/get-component)
|
|
1111
|
+
|
|
1112
|
+
#### Parameters
|
|
1113
|
+
|
|
1114
|
+
| Name | Type | Required | Notes |
|
|
1115
|
+
| -------------- | ------ | -------- | ----- |
|
|
1116
|
+
| `component_id` | string | Yes | |
|
|
1117
|
+
|
|
1118
|
+
#### Example
|
|
1119
|
+
|
|
1120
|
+
```ruby
|
|
1121
|
+
response = LoopsSdk::Components.get(component_id: "clp6q9r1s0154ouy7gmlovx90")
|
|
1122
|
+
```
|
|
1123
|
+
|
|
1124
|
+
---
|
|
1125
|
+
|
|
1126
|
+
### Campaigns.list()
|
|
1127
|
+
|
|
1128
|
+
List campaigns.
|
|
828
1129
|
|
|
829
|
-
|
|
1130
|
+
[API Reference](https://loops.so/docs/api-reference/list-campaigns)
|
|
1131
|
+
|
|
1132
|
+
#### Parameters
|
|
1133
|
+
|
|
1134
|
+
| Name | Type | Required | Notes |
|
|
1135
|
+
| --------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
1136
|
+
| `perPage` | integer | No | How many results to return per page. Must be between 10 and 50. Defaults to 20 if omitted. |
|
|
1137
|
+
| `cursor` | string | No | A cursor, to return a specific page of results. Cursors can be found from the `pagination.nextCursor` value in each response. |
|
|
1138
|
+
|
|
1139
|
+
#### Example
|
|
1140
|
+
|
|
1141
|
+
```ruby
|
|
1142
|
+
response = LoopsSdk::Campaigns.list
|
|
1143
|
+
```
|
|
1144
|
+
|
|
1145
|
+
---
|
|
1146
|
+
|
|
1147
|
+
### Campaigns.create()
|
|
1148
|
+
|
|
1149
|
+
Create a draft campaign. An empty email message is created automatically.
|
|
1150
|
+
|
|
1151
|
+
[API Reference](https://loops.so/docs/api-reference/create-campaign)
|
|
1152
|
+
|
|
1153
|
+
#### Parameters
|
|
1154
|
+
|
|
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: "..." }`. |
|
|
1163
|
+
|
|
1164
|
+
#### Example
|
|
1165
|
+
|
|
1166
|
+
```ruby
|
|
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
|
+
)
|
|
1174
|
+
```
|
|
1175
|
+
|
|
1176
|
+
---
|
|
1177
|
+
|
|
1178
|
+
### Campaigns.get()
|
|
1179
|
+
|
|
1180
|
+
Get a single campaign by ID.
|
|
1181
|
+
|
|
1182
|
+
[API Reference](https://loops.so/docs/api-reference/get-campaign)
|
|
1183
|
+
|
|
1184
|
+
#### Parameters
|
|
1185
|
+
|
|
1186
|
+
| Name | Type | Required | Notes |
|
|
1187
|
+
| ------------- | ------ | -------- | ----- |
|
|
1188
|
+
| `campaign_id` | string | Yes | |
|
|
1189
|
+
|
|
1190
|
+
#### Example
|
|
1191
|
+
|
|
1192
|
+
```ruby
|
|
1193
|
+
response = LoopsSdk::Campaigns.get(campaign_id: "cln4o7p9q0110msw5ekjtmv78")
|
|
1194
|
+
```
|
|
1195
|
+
|
|
1196
|
+
---
|
|
1197
|
+
|
|
1198
|
+
### Campaigns.update()
|
|
1199
|
+
|
|
1200
|
+
Update a draft campaign's name, group, audience, or scheduling.
|
|
1201
|
+
|
|
1202
|
+
[API Reference](https://loops.so/docs/api-reference/update-campaign)
|
|
1203
|
+
|
|
1204
|
+
#### Parameters
|
|
1205
|
+
|
|
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.
|
|
1217
|
+
|
|
1218
|
+
#### Example
|
|
1219
|
+
|
|
1220
|
+
```ruby
|
|
1221
|
+
response = LoopsSdk::Campaigns.update(
|
|
1222
|
+
campaign_id: "cln4o7p9q0110msw5ekjtmv78",
|
|
1223
|
+
name: "Updated campaign name"
|
|
1224
|
+
)
|
|
1225
|
+
```
|
|
1226
|
+
|
|
1227
|
+
---
|
|
1228
|
+
|
|
1229
|
+
### EmailMessages.get()
|
|
1230
|
+
|
|
1231
|
+
Get an email message, including its LMX content.
|
|
1232
|
+
|
|
1233
|
+
[API Reference](https://loops.so/docs/api-reference/get-email-message)
|
|
1234
|
+
|
|
1235
|
+
#### Parameters
|
|
1236
|
+
|
|
1237
|
+
| Name | Type | Required | Notes |
|
|
1238
|
+
| ------------------- | ------ | -------- | ----- |
|
|
1239
|
+
| `email_message_id` | string | Yes | |
|
|
1240
|
+
|
|
1241
|
+
#### Example
|
|
1242
|
+
|
|
1243
|
+
```ruby
|
|
1244
|
+
response = LoopsSdk::EmailMessages.get(email_message_id: "cly8k3m0n0044jpx2bghepq45")
|
|
1245
|
+
```
|
|
1246
|
+
|
|
1247
|
+
---
|
|
1248
|
+
|
|
1249
|
+
### EmailMessages.update()
|
|
1250
|
+
|
|
1251
|
+
Update an email message for a draft campaign.
|
|
1252
|
+
|
|
1253
|
+
[API Reference](https://loops.so/docs/api-reference/update-email-message)
|
|
1254
|
+
|
|
1255
|
+
#### Parameters
|
|
1256
|
+
|
|
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. |
|
|
1274
|
+
|
|
1275
|
+
#### Example
|
|
1276
|
+
|
|
1277
|
+
```ruby
|
|
1278
|
+
response = LoopsSdk::EmailMessages.update(
|
|
1279
|
+
email_message_id: "cly8k3m0n0044jpx2bghepq45",
|
|
1280
|
+
expected_revision_id: "clm9n4o6p0088lrz4dijslt67",
|
|
1281
|
+
subject: "Spring announcement",
|
|
1282
|
+
preview_text: "See what's new",
|
|
1283
|
+
from_name: "Loops",
|
|
1284
|
+
from_email: "hello",
|
|
1285
|
+
lmx: "<Email><Style /></Email>"
|
|
1286
|
+
)
|
|
1287
|
+
```
|
|
1288
|
+
|
|
1289
|
+
---
|
|
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" />)
|
|
830
1622
|
```
|
|
831
1623
|
|
|
832
1624
|
#### Response
|
|
833
1625
|
|
|
834
1626
|
```json
|
|
835
1627
|
{
|
|
836
|
-
"
|
|
837
|
-
|
|
838
|
-
"returnedResults": 20,
|
|
839
|
-
"perPage": 20,
|
|
840
|
-
"totalPages": 2,
|
|
841
|
-
"nextCursor": "clyo0q4wo01p59fsecyxqsh38",
|
|
842
|
-
"nextPage": "https://app.loops.so/api/v1/transactional?cursor=clyo0q4wo01p59fsecyxqsh38&perPage=20"
|
|
843
|
-
},
|
|
844
|
-
"data": [
|
|
845
|
-
{
|
|
846
|
-
"id": "clfn0k1yg001imo0fdeqg30i8",
|
|
847
|
-
"lastUpdated": "2023-11-06T17:48:07.249Z",
|
|
848
|
-
"dataVariables": []
|
|
849
|
-
},
|
|
850
|
-
{
|
|
851
|
-
"id": "cll42l54f20i1la0lfooe3z12",
|
|
852
|
-
"lastUpdated": "2025-02-02T02:56:28.845Z",
|
|
853
|
-
"dataVariables": [
|
|
854
|
-
"confirmationUrl"
|
|
855
|
-
]
|
|
856
|
-
},
|
|
857
|
-
{
|
|
858
|
-
"id": "clw6rbuwp01rmeiyndm80155l",
|
|
859
|
-
"lastUpdated": "2024-05-14T19:02:52.000Z",
|
|
860
|
-
"dataVariables": [
|
|
861
|
-
"firstName",
|
|
862
|
-
"lastName",
|
|
863
|
-
"inviteLink"
|
|
864
|
-
]
|
|
865
|
-
},
|
|
866
|
-
...
|
|
867
|
-
]
|
|
1628
|
+
"emailAssetId": "clu1v4w6x0254tz42lrcwat45",
|
|
1629
|
+
"finalUrl": "https://cdn.loops.so/clu1v4w6x0254tz42lrcwat45.png"
|
|
868
1630
|
}
|
|
869
1631
|
```
|
|
870
1632
|
|
|
@@ -878,4 +1640,4 @@ Run tests with `bundle exec rspec`.
|
|
|
878
1640
|
|
|
879
1641
|
## Contributing
|
|
880
1642
|
|
|
881
|
-
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
|
data/lib/loops_sdk/base.rb
CHANGED
|
@@ -7,13 +7,13 @@ module LoopsSdk
|
|
|
7
7
|
|
|
8
8
|
def handle_response(response)
|
|
9
9
|
case response.status
|
|
10
|
-
when 200
|
|
10
|
+
when 200, 201
|
|
11
11
|
JSON.parse(response.body)
|
|
12
12
|
when 429
|
|
13
13
|
limit = response.headers["x-ratelimit-limit"]
|
|
14
14
|
remaining = response.headers["x-ratelimit-remaining"]
|
|
15
15
|
raise RateLimitError.new(limit, remaining)
|
|
16
|
-
when 400, 404, 405, 409, 500
|
|
16
|
+
when 400, 401, 404, 405, 409, 413, 422, 500
|
|
17
17
|
raise APIError.new(response.status, response.body)
|
|
18
18
|
else
|
|
19
19
|
raise APIError.new(response.status, "Unexpected error occurred")
|
|
@@ -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
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LoopsSdk
|
|
4
|
+
class Campaigns < Base
|
|
5
|
+
class << self
|
|
6
|
+
def list(perPage: 20, cursor: nil)
|
|
7
|
+
make_request(method: :get, path: "v1/campaigns", params: { perPage: perPage, cursor: cursor })
|
|
8
|
+
end
|
|
9
|
+
|
|
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)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def get(campaign_id:)
|
|
23
|
+
make_request(method: :get, path: "v1/campaigns/#{campaign_id}")
|
|
24
|
+
end
|
|
25
|
+
|
|
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)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LoopsSdk
|
|
4
|
+
class Components < Base
|
|
5
|
+
class << self
|
|
6
|
+
def list(perPage: 20, cursor: nil)
|
|
7
|
+
make_request(method: :get, path: "v1/components", params: { perPage: perPage, cursor: cursor })
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def get(component_id:)
|
|
11
|
+
make_request(method: :get, path: "v1/components/#{component_id}")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LoopsSdk
|
|
4
|
+
class EmailMessages < Base
|
|
5
|
+
class << self
|
|
6
|
+
def get(email_message_id:)
|
|
7
|
+
make_request(method: :get, path: "v1/email-messages/#{email_message_id}")
|
|
8
|
+
end
|
|
9
|
+
|
|
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
|
+
)
|
|
27
|
+
body = {
|
|
28
|
+
expectedRevisionId: expected_revision_id,
|
|
29
|
+
subject: subject,
|
|
30
|
+
previewText: preview_text,
|
|
31
|
+
fromName: from_name,
|
|
32
|
+
fromEmail: from_email,
|
|
33
|
+
replyToEmail: reply_to_email,
|
|
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
|
|
42
|
+
}.compact
|
|
43
|
+
make_request(method: :post, path: "v1/email-messages/#{email_message_id}", body: body)
|
|
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
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LoopsSdk
|
|
4
|
+
class Themes < Base
|
|
5
|
+
class << self
|
|
6
|
+
def list(perPage: 20, cursor: nil)
|
|
7
|
+
make_request(method: :get, path: "v1/themes", params: { perPage: perPage, cursor: cursor })
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def get(theme_id:)
|
|
11
|
+
make_request(method: :get, path: "v1/themes/#{theme_id}")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
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
|
@@ -11,6 +11,16 @@ require_relative "loops_sdk/mailing_lists"
|
|
|
11
11
|
require_relative "loops_sdk/transactional"
|
|
12
12
|
require_relative "loops_sdk/contact_properties"
|
|
13
13
|
require_relative "loops_sdk/api_key"
|
|
14
|
+
require_relative "loops_sdk/dedicated_sending_ips"
|
|
15
|
+
require_relative "loops_sdk/themes"
|
|
16
|
+
require_relative "loops_sdk/components"
|
|
17
|
+
require_relative "loops_sdk/campaigns"
|
|
18
|
+
require_relative "loops_sdk/campaign_groups"
|
|
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"
|
|
14
24
|
|
|
15
25
|
module LoopsSdk
|
|
16
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,14 +35,24 @@ 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
|
|
41
|
+
- lib/loops_sdk/campaigns.rb
|
|
42
|
+
- lib/loops_sdk/components.rb
|
|
39
43
|
- lib/loops_sdk/configuration.rb
|
|
40
44
|
- lib/loops_sdk/contact_properties.rb
|
|
41
45
|
- lib/loops_sdk/contacts.rb
|
|
46
|
+
- lib/loops_sdk/dedicated_sending_ips.rb
|
|
47
|
+
- lib/loops_sdk/email_messages.rb
|
|
42
48
|
- lib/loops_sdk/events.rb
|
|
43
49
|
- lib/loops_sdk/mailing_lists.rb
|
|
50
|
+
- lib/loops_sdk/themes.rb
|
|
44
51
|
- lib/loops_sdk/transactional.rb
|
|
52
|
+
- lib/loops_sdk/transactional_groups.rb
|
|
53
|
+
- lib/loops_sdk/uploads.rb
|
|
45
54
|
- lib/loops_sdk/version.rb
|
|
55
|
+
- lib/loops_sdk/workflows.rb
|
|
46
56
|
homepage: https://loops.so/docs/api-reference
|
|
47
57
|
licenses:
|
|
48
58
|
- MIT
|