loops_sdk 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 65b81eba842a1765bb2bc99006cbcaab839e442b3ee90ea92076cef8fba8f942
4
- data.tar.gz: 3e544adfb4c2ed0b1069fc1a455773397a27a8254d9e8fe75ebbc33be2dfa9e8
3
+ metadata.gz: b5f428ed70457f4a5545ae8db80c8c1184053851702186b93e4181de19826bac
4
+ data.tar.gz: 273c41adcdfc013281b38e6e7fbf9d1d5f754e3e0e34979b660284689c26d9a6
5
5
  SHA512:
6
- metadata.gz: 565a16854a58cf5510b8c6c189394f7b62bea1aa6b1448e41dbb1759268d6f25fe9f366190a29896b974a49648e2068478db8e4622c9db3bbb2a29ef25aba855
7
- data.tar.gz: cd2b0f20ad57991723c3ca2bb68efe71b3759a0669a602be1c71583368fb7f3ae79dabbbb068ba9392918081edf9e465fcd4ee1f50c721ea5cbbcd2cc866d010
6
+ metadata.gz: cf08a088e5a500fe82ff04a7e432c4bae832a9414ba693c69f9d13ba381a85dcad63e554b09449f3c2f79c1e150a7309f5071b98c4a5a022820f044e93e8216b
7
+ data.tar.gz: fa693592b67828b4c1a351a938f2c16bc058f29830f442cab2d009383b9e07a108df1c1fb836c54066c067d0bce222a26f975994b16d1d3348a91780fc783fd5
data/README.md CHANGED
@@ -116,6 +116,17 @@ You can use custom contact properties in API calls. Please make sure to [add cus
116
116
  - [Events.send()](#eventssend)
117
117
  - [Transactional.send()](#transactionalsend)
118
118
  - [Transactional.list()](#transactionallist)
119
+ - [DedicatedSendingIps.list()](#dedicatedsendingipslist)
120
+ - [Themes.list()](#themeslist)
121
+ - [Themes.get()](#themesget)
122
+ - [Components.list()](#componentslist)
123
+ - [Components.get()](#componentsget)
124
+ - [Campaigns.list()](#campaignslist)
125
+ - [Campaigns.create()](#campaignscreate)
126
+ - [Campaigns.get()](#campaignsget)
127
+ - [Campaigns.update()](#campaignsupdate)
128
+ - [EmailMessages.get()](#emailmessagesget)
129
+ - [EmailMessages.update()](#emailmessagesupdate)
119
130
 
120
131
  ---
121
132
 
@@ -870,6 +881,256 @@ response = LoopsSdk::Transactional.list(perPage: 15)
870
881
 
871
882
  ---
872
883
 
884
+ ### DedicatedSendingIps.list()
885
+
886
+ Get Loops' dedicated sending IP addresses.
887
+
888
+ [API Reference](https://loops.so/docs/api-reference/list-dedicated-sending-ips)
889
+
890
+ #### Parameters
891
+
892
+ None
893
+
894
+ #### Example
895
+
896
+ ```ruby
897
+ response = LoopsSdk::DedicatedSendingIps.list
898
+ ```
899
+
900
+ #### Response
901
+
902
+ Returns an array of IP address strings.
903
+
904
+ ```json
905
+ ["1.2.3.4", "5.6.7.8"]
906
+ ```
907
+
908
+ ---
909
+
910
+ ### Themes.list()
911
+
912
+ List email themes.
913
+
914
+ [API Reference](https://loops.so/docs/api-reference/list-themes)
915
+
916
+ #### Parameters
917
+
918
+ | Name | Type | Required | Notes |
919
+ | --------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
920
+ | `perPage` | integer | No | How many results to return per page. Must be between 10 and 50. Defaults to 20 if omitted. |
921
+ | `cursor` | string | No | A cursor, to return a specific page of results. Cursors can be found from the `pagination.nextCursor` value in each response. |
922
+
923
+ #### Example
924
+
925
+ ```ruby
926
+ response = LoopsSdk::Themes.list
927
+
928
+ response = LoopsSdk::Themes.list(perPage: 15, cursor: "cursor_value")
929
+ ```
930
+
931
+ ---
932
+
933
+ ### Themes.get()
934
+
935
+ Get a single theme by ID.
936
+
937
+ [API Reference](https://loops.so/docs/api-reference/get-theme)
938
+
939
+ #### Parameters
940
+
941
+ | Name | Type | Required | Notes |
942
+ | ---------- | ------ | -------- | ----- |
943
+ | `theme_id` | string | Yes | |
944
+
945
+ #### Example
946
+
947
+ ```ruby
948
+ response = LoopsSdk::Themes.get(theme_id: "theme_123")
949
+ ```
950
+
951
+ ---
952
+
953
+ ### Components.list()
954
+
955
+ List email components.
956
+
957
+ [API Reference](https://loops.so/docs/api-reference/list-components)
958
+
959
+ #### Parameters
960
+
961
+ | Name | Type | Required | Notes |
962
+ | --------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
963
+ | `perPage` | integer | No | How many results to return per page. Must be between 10 and 50. Defaults to 20 if omitted. |
964
+ | `cursor` | string | No | A cursor, to return a specific page of results. Cursors can be found from the `pagination.nextCursor` value in each response. |
965
+
966
+ #### Example
967
+
968
+ ```ruby
969
+ response = LoopsSdk::Components.list
970
+ ```
971
+
972
+ ---
973
+
974
+ ### Components.get()
975
+
976
+ Get a single component by ID.
977
+
978
+ [API Reference](https://loops.so/docs/api-reference/get-component)
979
+
980
+ #### Parameters
981
+
982
+ | Name | Type | Required | Notes |
983
+ | -------------- | ------ | -------- | ----- |
984
+ | `component_id` | string | Yes | |
985
+
986
+ #### Example
987
+
988
+ ```ruby
989
+ response = LoopsSdk::Components.get(component_id: "component_123")
990
+ ```
991
+
992
+ ---
993
+
994
+ ### Campaigns.list()
995
+
996
+ List campaigns.
997
+
998
+ [API Reference](https://loops.so/docs/api-reference/list-campaigns)
999
+
1000
+ #### Parameters
1001
+
1002
+ | Name | Type | Required | Notes |
1003
+ | --------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
1004
+ | `perPage` | integer | No | How many results to return per page. Must be between 10 and 50. Defaults to 20 if omitted. |
1005
+ | `cursor` | string | No | A cursor, to return a specific page of results. Cursors can be found from the `pagination.nextCursor` value in each response. |
1006
+
1007
+ #### Example
1008
+
1009
+ ```ruby
1010
+ response = LoopsSdk::Campaigns.list
1011
+ ```
1012
+
1013
+ ---
1014
+
1015
+ ### Campaigns.create()
1016
+
1017
+ Create a draft campaign. An empty email message is created automatically.
1018
+
1019
+ [API Reference](https://loops.so/docs/api-reference/create-campaign)
1020
+
1021
+ #### Parameters
1022
+
1023
+ | Name | Type | Required | Notes |
1024
+ | ------ | ------ | -------- | ----- |
1025
+ | `name` | string | Yes | |
1026
+
1027
+ #### Example
1028
+
1029
+ ```ruby
1030
+ response = LoopsSdk::Campaigns.create(name: "Spring announcement")
1031
+ ```
1032
+
1033
+ ---
1034
+
1035
+ ### Campaigns.get()
1036
+
1037
+ Get a single campaign by ID.
1038
+
1039
+ [API Reference](https://loops.so/docs/api-reference/get-campaign)
1040
+
1041
+ #### Parameters
1042
+
1043
+ | Name | Type | Required | Notes |
1044
+ | ------------- | ------ | -------- | ----- |
1045
+ | `campaign_id` | string | Yes | |
1046
+
1047
+ #### Example
1048
+
1049
+ ```ruby
1050
+ response = LoopsSdk::Campaigns.get(campaign_id: "campaign_123")
1051
+ ```
1052
+
1053
+ ---
1054
+
1055
+ ### Campaigns.update()
1056
+
1057
+ Update a draft campaign's name.
1058
+
1059
+ [API Reference](https://loops.so/docs/api-reference/update-campaign)
1060
+
1061
+ #### Parameters
1062
+
1063
+ | Name | Type | Required | Notes |
1064
+ | ------------- | ------ | -------- | ----- |
1065
+ | `campaign_id` | string | Yes | |
1066
+ | `name` | string | Yes | |
1067
+
1068
+ #### Example
1069
+
1070
+ ```ruby
1071
+ response = LoopsSdk::Campaigns.update(
1072
+ campaign_id: "campaign_123",
1073
+ name: "Updated campaign name"
1074
+ )
1075
+ ```
1076
+
1077
+ ---
1078
+
1079
+ ### EmailMessages.get()
1080
+
1081
+ Get an email message, including its LMX content.
1082
+
1083
+ [API Reference](https://loops.so/docs/api-reference/get-email-message)
1084
+
1085
+ #### Parameters
1086
+
1087
+ | Name | Type | Required | Notes |
1088
+ | ------------------- | ------ | -------- | ----- |
1089
+ | `email_message_id` | string | Yes | |
1090
+
1091
+ #### Example
1092
+
1093
+ ```ruby
1094
+ response = LoopsSdk::EmailMessages.get(email_message_id: "message_123")
1095
+ ```
1096
+
1097
+ ---
1098
+
1099
+ ### EmailMessages.update()
1100
+
1101
+ Update an email message for a draft campaign.
1102
+
1103
+ [API Reference](https://loops.so/docs/api-reference/update-email-message)
1104
+
1105
+ #### Parameters
1106
+
1107
+ | Name | Type | Required | Notes |
1108
+ | ------------------------ | ------ | -------- | ---------------------------------------------------------------------------------------------------------- |
1109
+ | `email_message_id` | string | Yes | |
1110
+ | `expected_revision_id` | string | No | The `contentRevisionId` from your last fetch. Required to avoid stale concurrent updates. |
1111
+ | `subject` | string | No | |
1112
+ | `preview_text` | string | No | |
1113
+ | `from_name` | string | No | |
1114
+ | `from_email` | string | No | Sender username without `@` or domain. The team's sending domain is appended automatically. |
1115
+ | `reply_to_email` | string | No | Must be empty or a valid email address. |
1116
+ | `lmx` | string | No | Email body serialized as LMX. Styles must be embedded in the LMX `<Style />` tag. |
1117
+
1118
+ #### Example
1119
+
1120
+ ```ruby
1121
+ response = LoopsSdk::EmailMessages.update(
1122
+ email_message_id: "message_123",
1123
+ expected_revision_id: "revision_123",
1124
+ subject: "Spring announcement",
1125
+ preview_text: "See what's new",
1126
+ from_name: "Loops",
1127
+ from_email: "hello",
1128
+ lmx: "<Email><Style /></Email>"
1129
+ )
1130
+ ```
1131
+
1132
+ ---
1133
+
873
1134
  ## Testing
874
1135
 
875
1136
  Run tests with `bundle exec rspec`.
@@ -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,23 @@
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:)
11
+ make_request(method: :post, path: "v1/campaigns", body: { name: name })
12
+ end
13
+
14
+ def get(campaign_id:)
15
+ make_request(method: :get, path: "v1/campaigns/#{campaign_id}")
16
+ end
17
+
18
+ def update(campaign_id:, name:)
19
+ make_request(method: :post, path: "v1/campaigns/#{campaign_id}", body: { name: name })
20
+ end
21
+ end
22
+ end
23
+ 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,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LoopsSdk
4
+ class DedicatedSendingIps < Base
5
+ class << self
6
+ def list
7
+ make_request(method: :get, path: "v1/dedicated-sending-ips")
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,24 @@
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(email_message_id:, expected_revision_id: nil, subject: nil, preview_text: nil, from_name: nil, from_email: nil, reply_to_email: nil, lmx: nil)
11
+ body = {
12
+ expectedRevisionId: expected_revision_id,
13
+ subject: subject,
14
+ previewText: preview_text,
15
+ fromName: from_name,
16
+ fromEmail: from_email,
17
+ replyToEmail: reply_to_email,
18
+ lmx: lmx
19
+ }.compact
20
+ make_request(method: :post, path: "v1/email-messages/#{email_message_id}", body: body)
21
+ end
22
+ end
23
+ end
24
+ 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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LoopsSdk
4
- VERSION = "2.1.0"
4
+ VERSION = "2.2.0"
5
5
  end
data/lib/loops_sdk.rb CHANGED
@@ -11,6 +11,11 @@ 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/email_messages"
14
19
 
15
20
  module LoopsSdk
16
21
  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.1.0
4
+ version: 2.2.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-04-08 00:00:00.000000000 Z
11
+ date: 2026-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -36,11 +36,16 @@ files:
36
36
  - lib/loops_sdk.rb
37
37
  - lib/loops_sdk/api_key.rb
38
38
  - lib/loops_sdk/base.rb
39
+ - lib/loops_sdk/campaigns.rb
40
+ - lib/loops_sdk/components.rb
39
41
  - lib/loops_sdk/configuration.rb
40
42
  - lib/loops_sdk/contact_properties.rb
41
43
  - lib/loops_sdk/contacts.rb
44
+ - lib/loops_sdk/dedicated_sending_ips.rb
45
+ - lib/loops_sdk/email_messages.rb
42
46
  - lib/loops_sdk/events.rb
43
47
  - lib/loops_sdk/mailing_lists.rb
48
+ - lib/loops_sdk/themes.rb
44
49
  - lib/loops_sdk/transactional.rb
45
50
  - lib/loops_sdk/version.rb
46
51
  homepage: https://loops.so/docs/api-reference