resend 0.27.0 → 1.0.1

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: d14aa64ac124d647f4fb79b7f408e485fb91c67289a6e085fe39bca75e602793
4
- data.tar.gz: c4302a083a1b6c2ed08ae62825ea1383ee53644967b59e9279d6489863dfdbdd
3
+ metadata.gz: 67dadb5f7acb77801501030612149bf52b6c46626fd5630a233a77ab6fc552d7
4
+ data.tar.gz: 8842020484f59a566282b8ff1258bfeea02594274b2f117c548ae2ad49284ad2
5
5
  SHA512:
6
- metadata.gz: e1d6b730a10d67e4643d11b24ab11c9c26007ef874505fa0afd569009e16449c073c978a82d734f108f3f71660762b7591c3c8b95f2fabd15574622b30ff80b7
7
- data.tar.gz: 8f0bab76e49b940813ce73dc71daebe1a3a3f423d27b4fecfb89db06460949f80c15da300a1d5d82c4768006ba0bff0e7b641b5a0360830751f413932ae886e8
6
+ metadata.gz: d889989325170107795bed29b590b45382909a8b4812381c4fa330e8c94c6cf7d8c3be1474793c0b6a93c85fc3f0647fd868f5b540902cd9e6ca260821f3b5ec
7
+ data.tar.gz: 48ec677afd58504f02b4099fb1f4d926defa2aa64f05cb2d8e8e1c724b08f1d1b3950f79535ac89481a8f58f1b1884962c4e46247bbdb6b03e0364325822fab9
data/CHANGELOG.md ADDED
@@ -0,0 +1,131 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2025-10-31
9
+
10
+ ### Overview
11
+
12
+ This major release introduces breaking changes to the Contacts API and deprecates the Audiences API in favor of Segments. **If you only use the SDK for sending emails or the Audiences API, you can upgrade to v1.0.0 without any code changes.** The breaking changes are limited to the Contacts API only.
13
+
14
+ ### ⚠️ BREAKING CHANGES
15
+
16
+ #### Contacts API Changes
17
+
18
+ - ⚠️ **Change `Contacts.create` to accept hash parameter with optional `audience_id`** - Previously required `audience_id` in params, now it's optional. Supports global contacts.
19
+ - ⚠️ **Change `Contacts.get` from `get(audience_id, id)` to `get(params)`** - Now accepts a hash with optional `audience_id` and required `id` or `email`. Raises `ArgumentError: "Missing \`id\` or \`email\` field"` when neither is provided.
20
+ - ⚠️ **Change `Contacts.list` from `list(audience_id, params = {})` to `list(params = {})`** - Now accepts a hash with optional `audience_id` and pagination params
21
+ - ⚠️ **Change `Contacts.remove` from `remove(audience_id, contact_id)` to `remove(params)`** - Now accepts a hash with optional `audience_id` and required `id` or `email`. Raises `ArgumentError: "Missing \`id\` or \`email\` field"` when neither is provided.
22
+ - ⚠️ **Change `Contacts.update` error message** - Error changed from `"id or email is required"` to `"Missing \`id\` or \`email\` field"` to match Node.js SDK format
23
+ - ⚠️ **Change `Contacts.update` to accept optional `audience_id`** - Previously required `audience_id` in params, now it's optional
24
+
25
+ **Before (v0.x):**
26
+
27
+ ```ruby
28
+ # Methods used positional arguments and required audience_id
29
+ Resend::Contacts.create(audience_id: "aud_123", email: "user@example.com", first_name: "John")
30
+ contact = Resend::Contacts.get("aud_123", "contact_123")
31
+ contacts = Resend::Contacts.list("aud_123")
32
+ contacts = Resend::Contacts.list("aud_123", limit: 10)
33
+ Resend::Contacts.update(audience_id: "aud_123", id: "contact_123", first_name: "Jane")
34
+ Resend::Contacts.remove("aud_123", "contact_123")
35
+ ```
36
+
37
+ **After (v1.0.0):**
38
+
39
+ ```ruby
40
+ # Methods use hash parameters and support optional audience_id
41
+ # Global contacts (no audience_id)
42
+ Resend::Contacts.create(email: "user@example.com", first_name: "John")
43
+ contact = Resend::Contacts.get(id: "contact_123")
44
+ contact = Resend::Contacts.get(email: "user@example.com")
45
+ contacts = Resend::Contacts.list
46
+ contacts = Resend::Contacts.list(limit: 10)
47
+ Resend::Contacts.update(id: "contact_123", first_name: "Jane")
48
+ Resend::Contacts.remove(id: "contact_123")
49
+
50
+ # Audience-scoped contacts (with audience_id)
51
+ Resend::Contacts.create(audience_id: "aud_123", email: "user@example.com", first_name: "John")
52
+ contact = Resend::Contacts.get(audience_id: "aud_123", id: "contact_123")
53
+ contacts = Resend::Contacts.list(audience_id: "aud_123", limit: 10)
54
+ Resend::Contacts.update(audience_id: "aud_123", id: "contact_123", first_name: "Jane")
55
+ Resend::Contacts.remove(audience_id: "aud_123", id: "contact_123")
56
+ ```
57
+
58
+ #### Audiences API Deprecated
59
+
60
+ - ⚠️ **Deprecate `Resend::Audiences` in favor of `Resend::Segments`** - The Audiences module has been replaced with Segments. A backward-compatible alias `Audiences = Segments` has been added, so existing code will continue to work.
61
+
62
+ **Migration (Recommended):**
63
+
64
+ Update your code to use `Segments` instead of `Audiences`:
65
+
66
+ ```ruby
67
+ # Before (still works but deprecated)
68
+ Resend::Audiences.create(name: "My Audience")
69
+ Resend::Audiences.get("audience_123")
70
+ Resend::Audiences.list
71
+ Resend::Audiences.remove("audience_123")
72
+
73
+ # After (recommended)
74
+ Resend::Segments.create(name: "My Segment")
75
+ Resend::Segments.get("segment_123")
76
+ Resend::Segments.list
77
+ Resend::Segments.remove("segment_123")
78
+ ```
79
+
80
+ **Note:** The `Audiences` alias is deprecated and may be removed in a future major version. Please migrate to `Segments`.
81
+
82
+ ### Added
83
+
84
+ #### New API Modules
85
+
86
+ - Add `Resend::Templates` API for managing email templates
87
+ - `Templates.create` - Create a new template
88
+ - `Templates.get` - Retrieve a template by ID
89
+ - `Templates.update` - Update an existing template
90
+ - `Templates.publish` - Publish a template
91
+ - `Templates.duplicate` - Duplicate an existing template
92
+ - `Templates.list` - List all templates with pagination
93
+ - `Templates.remove` - Delete a template
94
+ - Add `Resend::Topics` API for managing topics
95
+ - `Topics.create` - Create a new topic
96
+ - `Topics.get` - Retrieve a topic by ID
97
+ - `Topics.update` - Update a topic
98
+ - `Topics.list` - List all topics with pagination
99
+ - `Topics.remove` - Delete a topic
100
+ - Add `Resend::Segments` API for managing segments (replacement for Audiences)
101
+ - `Segments.create` - Create a new segment
102
+ - `Segments.get` - Retrieve a segment by ID
103
+ - `Segments.list` - List all segments
104
+ - `Segments.remove` - Delete a segment
105
+ - Add `Resend::ContactProperties` API for managing custom contact properties
106
+ - `ContactProperties.update` - Update contact properties (validates and raises `ArgumentError: "Missing \`id\` field"` when id is not provided)
107
+ - `ContactProperties.get` - Retrieve contact properties by ID
108
+ - Add `Resend::Contacts::Segments` API for managing contact-segment relationships
109
+ - `Contacts::Segments.list` - List all segments for a contact
110
+ - `Contacts::Segments.add` - Add a contact to a segment
111
+ - `Contacts::Segments.remove` - Remove a contact from a segment
112
+ - Add `Resend::Contacts::Topics` API for managing contact topic subscriptions
113
+ - `Contacts::Topics.list` - List topic subscriptions for a contact
114
+ - `Contacts::Topics.update` - Update topic subscriptions (opt-in/opt-out) for a contact
115
+
116
+ #### Contacts API Enhancements
117
+
118
+ - Add support for `email` parameter in `Contacts.get` and `Contacts.remove` methods (can now use email instead of ID)
119
+ - Add `audience_id` support in Contacts API methods for scoped operations
120
+ - Add support for global contacts (contacts not scoped to a specific audience/segment)
121
+ - Add validation error messages matching Node.js SDK format with backticks around field names
122
+
123
+ #### Broadcasts API Updates
124
+
125
+ - Add deprecation warnings for `audience_id` in `Broadcasts.create` and `Broadcasts.update` (use `segment_id` instead)
126
+
127
+ ### Removed
128
+
129
+ - Remove deprecated `send_email` method from `Resend::Emails` module (use `Resend::Emails.send` instead)
130
+
131
+ [1.0.0]: https://github.com/resend/resend-ruby/compare/v0.26.0...v1.0.0
@@ -5,13 +5,26 @@ module Resend
5
5
  module Broadcasts
6
6
  class << self
7
7
  # https://resend.com/docs/api-reference/broadcasts/create-broadcast
8
+ # @note Supports both segment_id and audience_id. At least one is required.
9
+ # audience_id is deprecated - use segment_id instead.
10
+ # @note When send: true is passed, the broadcast is sent immediately instead of
11
+ # creating a draft. When using send: true, you can also include scheduled_at
12
+ # to schedule the broadcast. Passing scheduled_at without send: true is an error.
8
13
  def create(params = {})
14
+ if params[:audience_id] && !params[:segment_id]
15
+ warn "[DEPRECATION] Using audience_id in broadcasts is deprecated. Use segment_id instead."
16
+ end
9
17
  path = "broadcasts"
10
18
  Resend::Request.new(path, params, "post").perform
11
19
  end
12
20
 
13
21
  # https://resend.com/docs/api-reference/broadcasts/update-broadcast
22
+ # @note Supports both segment_id and audience_id. At least one may be required.
23
+ # audience_id is deprecated - use segment_id instead.
14
24
  def update(params = {})
25
+ if params[:audience_id] && !params[:segment_id]
26
+ warn "[DEPRECATION] Using audience_id in broadcasts is deprecated. Use segment_id instead."
27
+ end
15
28
  path = "broadcasts/#{params[:broadcast_id]}"
16
29
  Resend::Request.new(path, params, "patch").perform
17
30
  end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resend
4
+ # Module for managing contact properties
5
+ #
6
+ # Contact properties allow you to store custom data about your contacts
7
+ module ContactProperties
8
+ class << self
9
+ # Create a custom property for your contacts
10
+ #
11
+ # @param params [Hash] Parameters for creating a contact property
12
+ # @option params [String] :key The property key (max 50 characters, alphanumeric and underscores only) (required)
13
+ # @option params [String] :type The property type ('string' or 'number') (required)
14
+ # @option params [String, Integer] :fallback_value The default value when property is not set (must match type)
15
+ #
16
+ # @return [Hash] Response containing the created contact property
17
+ #
18
+ # @example Create a string property
19
+ # Resend::ContactProperties.create({
20
+ # key: 'company_name',
21
+ # type: 'string',
22
+ # fallback_value: 'Acme Corp'
23
+ # })
24
+ #
25
+ # @example Create a number property
26
+ # Resend::ContactProperties.create({
27
+ # key: 'age',
28
+ # type: 'number',
29
+ # fallback_value: 0
30
+ # })
31
+ def create(params)
32
+ path = "contact-properties"
33
+ Resend::Request.new(path, params, "post").perform
34
+ end
35
+
36
+ # Retrieve a contact property by its ID
37
+ #
38
+ # @param contact_property_id [String] The Contact Property ID
39
+ #
40
+ # @return [Hash] Response containing the contact property details
41
+ #
42
+ # @example Get a contact property
43
+ # Resend::ContactProperties.get('b6d24b8e-af0b-4c3c-be0c-359bbd97381e')
44
+ def get(contact_property_id = "")
45
+ path = "contact-properties/#{contact_property_id}"
46
+ Resend::Request.new(path, {}, "get").perform
47
+ end
48
+
49
+ # Retrieve a list of contact properties
50
+ #
51
+ # @param params [Hash] Optional query parameters
52
+ # @option params [Integer] :limit Number of contact properties to retrieve (1-100, default: 20)
53
+ # @option params [String] :after The ID after which to retrieve more contact properties
54
+ # @option params [String] :before The ID before which to retrieve more contact properties
55
+ #
56
+ # @return [Hash] Response containing list of contact properties
57
+ #
58
+ # @example List all contact properties
59
+ # Resend::ContactProperties.list
60
+ #
61
+ # @example List with pagination
62
+ # Resend::ContactProperties.list({ limit: 10, after: 'cursor_123' })
63
+ def list(params = {})
64
+ path = Resend::PaginationHelper.build_paginated_path("contact-properties", params)
65
+ Resend::Request.new(path, {}, "get").perform
66
+ end
67
+
68
+ # Update an existing contact property
69
+ #
70
+ # Note: The 'key' and 'type' fields cannot be changed after creation
71
+ #
72
+ # @param params [Hash] Parameters for updating a contact property
73
+ # @option params [String] :id The Contact Property ID (required)
74
+ # @option params [String, Integer] :fallback_value The default value when property is not set
75
+ # (must match property type)
76
+ #
77
+ # @return [Hash] Response containing the updated contact property
78
+ #
79
+ # @example Update fallback value
80
+ # Resend::ContactProperties.update({
81
+ # id: 'b6d24b8e-af0b-4c3c-be0c-359bbd97381e',
82
+ # fallback_value: 'Example Company'
83
+ # })
84
+ def update(params)
85
+ raise ArgumentError, "Missing `id` field" if params[:id].nil?
86
+
87
+ contact_property_id = params[:id]
88
+ path = "contact-properties/#{contact_property_id}"
89
+ Resend::Request.new(path, params, "patch").perform
90
+ end
91
+
92
+ # Remove an existing contact property
93
+ #
94
+ # @param contact_property_id [String] The Contact Property ID
95
+ #
96
+ # @return [Hash] Response containing the deleted property ID and confirmation
97
+ #
98
+ # @example Delete a contact property
99
+ # Resend::ContactProperties.remove('b6d24b8e-af0b-4c3c-be0c-359bbd97381e')
100
+ def remove(contact_property_id = "")
101
+ path = "contact-properties/#{contact_property_id}"
102
+ Resend::Request.new(path, {}, "delete").perform
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resend
4
+ module Contacts
5
+ # Contact Segments api wrapper
6
+ module Segments
7
+ class << self
8
+ #
9
+ # List all segments for a contact
10
+ #
11
+ # @param params [Hash] the parameters
12
+ # @option params [String] :contact_id the contact id (either contact_id or email is required)
13
+ # @option params [String] :email the contact email (either contact_id or email is required)
14
+ # @option params [Integer] :limit the maximum number of results to return (optional)
15
+ # @option params [String] :after the cursor for pagination (optional)
16
+ # @option params [String] :before the cursor for pagination (optional)
17
+ #
18
+ # https://resend.com/docs/api-reference/contacts/list-contact-segments
19
+ def list(params)
20
+ raise ArgumentError, "contact_id or email is required" if params[:contact_id].nil? && params[:email].nil?
21
+
22
+ identifier = params[:contact_id] || params[:email]
23
+ base_path = "contacts/#{identifier}/segments"
24
+ path = Resend::PaginationHelper.build_paginated_path(base_path, params)
25
+ Resend::Request.new(path, {}, "get").perform
26
+ end
27
+
28
+ #
29
+ # Add a contact to a segment
30
+ #
31
+ # @param params [Hash] the parameters
32
+ # @option params [String] :contact_id the contact id (either contact_id or email is required)
33
+ # @option params [String] :email the contact email (either contact_id or email is required)
34
+ # @option params [String] :segment_id the segment id (required)
35
+ #
36
+ # https://resend.com/docs/api-reference/contacts/add-contact-to-segment
37
+ def add(params)
38
+ raise ArgumentError, "contact_id or email is required" if params[:contact_id].nil? && params[:email].nil?
39
+ raise ArgumentError, "segment_id is required" if params[:segment_id].nil?
40
+
41
+ identifier = params[:contact_id] || params[:email]
42
+ path = "contacts/#{identifier}/segments/#{params[:segment_id]}"
43
+ Resend::Request.new(path, {}, "post").perform
44
+ end
45
+
46
+ #
47
+ # Remove a contact from a segment
48
+ #
49
+ # @param params [Hash] the parameters
50
+ # @option params [String] :contact_id the contact id (either contact_id or email is required)
51
+ # @option params [String] :email the contact email (either contact_id or email is required)
52
+ # @option params [String] :segment_id the segment id (required)
53
+ #
54
+ # https://resend.com/docs/api-reference/contacts/remove-contact-from-segment
55
+ def remove(params)
56
+ raise ArgumentError, "contact_id or email is required" if params[:contact_id].nil? && params[:email].nil?
57
+ raise ArgumentError, "segment_id is required" if params[:segment_id].nil?
58
+
59
+ identifier = params[:contact_id] || params[:email]
60
+ path = "contacts/#{identifier}/segments/#{params[:segment_id]}"
61
+ Resend::Request.new(path, {}, "delete").perform
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resend
4
+ module Contacts
5
+ # Module for managing contact topic subscriptions
6
+ #
7
+ # Allows you to manage which topics contacts are subscribed to
8
+ module Topics
9
+ class << self
10
+ # Retrieve a list of topics subscriptions for a contact
11
+ #
12
+ # @param params [Hash] Parameters for listing topics
13
+ # @option params [String] :id The Contact ID (either :id or :email must be provided)
14
+ # @option params [String] :email The Contact Email (either :id or :email must be provided)
15
+ # @option params [Integer] :limit Number of topics to retrieve (1-100)
16
+ # @option params [String] :after The ID after which to retrieve more topics
17
+ # @option params [String] :before The ID before which to retrieve more topics
18
+ #
19
+ # @return [Hash] Response containing list of topics with subscription status
20
+ #
21
+ # @example List topics by contact ID
22
+ # Resend::Contacts::Topics.list(id: 'e169aa45-1ecf-4183-9955-b1499d5701d3')
23
+ #
24
+ # @example List topics by contact email
25
+ # Resend::Contacts::Topics.list(email: 'steve.wozniak@gmail.com')
26
+ #
27
+ # @example List topics with pagination
28
+ # Resend::Contacts::Topics.list(id: 'contact-id', limit: 10, after: 'cursor_123')
29
+ def list(params = {})
30
+ contact_identifier = params[:id] || params[:email]
31
+ raise ArgumentError, "Either :id or :email must be provided" if contact_identifier.nil?
32
+
33
+ pagination_params = params.slice(:limit, :after, :before)
34
+ base_path = "contacts/#{contact_identifier}/topics"
35
+ path = Resend::PaginationHelper.build_paginated_path(base_path, pagination_params)
36
+
37
+ Resend::Request.new(path, {}, "get").perform
38
+ end
39
+
40
+ # Update topic subscriptions for a contact
41
+ #
42
+ # @param params [Hash] Parameters for updating topics
43
+ # @option params [String] :id The Contact ID (either :id or :email must be provided)
44
+ # @option params [String] :email The Contact Email (either :id or :email must be provided)
45
+ # @option params [Array<Hash>] :topics Array of topic subscription updates
46
+ # Each topic hash should contain:
47
+ # - :id [String] The Topic ID (required)
48
+ # - :subscription [String] The subscription action: 'opt_in' or 'opt_out' (required)
49
+ #
50
+ # @return [Hash] Response containing the contact ID
51
+ #
52
+ # @example Update by contact ID
53
+ # Resend::Contacts::Topics.update({
54
+ # id: 'e169aa45-1ecf-4183-9955-b1499d5701d3',
55
+ # topics: [
56
+ # { id: 'b6d24b8e-af0b-4c3c-be0c-359bbd97381e', subscription: 'opt_out' },
57
+ # { id: '07d84122-7224-4881-9c31-1c048e204602', subscription: 'opt_in' }
58
+ # ]
59
+ # })
60
+ #
61
+ # @example Update by contact email
62
+ # Resend::Contacts::Topics.update({
63
+ # email: 'steve.wozniak@gmail.com',
64
+ # topics: [
65
+ # { id: '07d84122-7224-4881-9c31-1c048e204602', subscription: 'opt_out' }
66
+ # ]
67
+ # })
68
+ def update(params)
69
+ contact_identifier = params[:id] || params[:email]
70
+ raise ArgumentError, "Either :id or :email must be provided" if contact_identifier.nil?
71
+
72
+ path = "contacts/#{contact_identifier}/topics"
73
+ body = params[:topics]
74
+
75
+ Resend::Request.new(path, body, "patch").perform
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -6,42 +6,96 @@ module Resend
6
6
  class << self
7
7
  # https://resend.com/docs/api-reference/contacts/create-contact
8
8
  def create(params)
9
- path = "audiences/#{params[:audience_id]}/contacts"
10
- Resend::Request.new(path, params, "post").perform
9
+ if params[:audience_id]
10
+ path = "audiences/#{params[:audience_id]}/contacts"
11
+ # Audience-scoped contacts don't support properties
12
+ payload = params.reject { |key, _| key == :properties }
13
+ else
14
+ path = "contacts"
15
+ payload = params
16
+ end
17
+ Resend::Request.new(path, payload, "post").perform
11
18
  end
12
19
 
13
20
  #
14
- # Retrieves a contact from an audience
21
+ # Retrieves a contact
15
22
  #
16
- # @param audience_id [String] the audience id
17
- # @param id [String] either the contact id or contact's email
23
+ # @param params [Hash] the parameters
24
+ # @option params [String] :id either the contact id or contact's email (required)
25
+ # @option params [String] :audience_id optional audience id to scope the operation
26
+ #
27
+ # @example Get contact by ID
28
+ # Resend::Contacts.get(id: "contact_123")
29
+ #
30
+ # @example Get contact scoped to an audience
31
+ # Resend::Contacts.get(id: "contact_123", audience_id: "aud_456")
18
32
  #
19
33
  # https://resend.com/docs/api-reference/contacts/get-contact
20
- def get(audience_id, id)
21
- path = "audiences/#{audience_id}/contacts/#{id}"
34
+ def get(params = {})
35
+ raise ArgumentError, "Missing `id` or `email` field" if params[:id].nil? && params[:email].nil?
36
+
37
+ audience_id = params[:audience_id]
38
+ contact_id = params[:id] || params[:email]
39
+ path = if audience_id
40
+ "audiences/#{audience_id}/contacts/#{contact_id}"
41
+ else
42
+ "contacts/#{contact_id}"
43
+ end
22
44
  Resend::Request.new(path, {}, "get").perform
23
45
  end
24
46
 
25
47
  #
26
- # List contacts in an audience
48
+ # List contacts
49
+ #
50
+ # @param params [Hash] optional parameters including pagination
51
+ # @option params [String] :audience_id optional audience id to scope the operation
52
+ # @option params [Integer] :limit number of records to return
53
+ # @option params [String] :cursor pagination cursor
54
+ #
55
+ # @example List all contacts
56
+ # Resend::Contacts.list
57
+ #
58
+ # @example List contacts with pagination
59
+ # Resend::Contacts.list(limit: 10)
60
+ #
61
+ # @example List contacts scoped to an audience
62
+ # Resend::Contacts.list(audience_id: "aud_456", limit: 10)
27
63
  #
28
- # @param audience_id [String] the audience id
29
- # @param params [Hash] optional pagination parameters
30
64
  # https://resend.com/docs/api-reference/contacts/list-contacts
31
- def list(audience_id, params = {})
32
- path = Resend::PaginationHelper.build_paginated_path("audiences/#{audience_id}/contacts", params)
65
+ def list(params = {})
66
+ audience_id = params[:audience_id]
67
+ path = if audience_id
68
+ Resend::PaginationHelper.build_paginated_path("audiences/#{audience_id}/contacts", params)
69
+ else
70
+ Resend::PaginationHelper.build_paginated_path("contacts", params)
71
+ end
33
72
  Resend::Request.new(path, {}, "get").perform
34
73
  end
35
74
 
36
75
  #
37
- # Remove a contact from an audience
76
+ # Remove a contact
77
+ #
78
+ # @param params [Hash] the parameters
79
+ # @option params [String] :id either the contact id or contact email (required)
80
+ # @option params [String] :audience_id optional audience id to scope the operation
38
81
  #
39
- # @param audience_id [String] the audience id
40
- # @param contact_id [String] either the contact id or contact email
82
+ # @example Remove contact by ID
83
+ # Resend::Contacts.remove(id: "contact_123")
41
84
  #
42
- # see also: https://resend.com/docs/api-reference/contacts/delete-contact
43
- def remove(audience_id, contact_id)
44
- path = "audiences/#{audience_id}/contacts/#{contact_id}"
85
+ # @example Remove contact scoped to an audience
86
+ # Resend::Contacts.remove(id: "contact_123", audience_id: "aud_456")
87
+ #
88
+ # https://resend.com/docs/api-reference/contacts/delete-contact
89
+ def remove(params = {})
90
+ raise ArgumentError, "Missing `id` or `email` field" if params[:id].nil? && params[:email].nil?
91
+
92
+ audience_id = params[:audience_id]
93
+ contact_id = params[:id] || params[:email]
94
+ path = if audience_id
95
+ "audiences/#{audience_id}/contacts/#{contact_id}"
96
+ else
97
+ "contacts/#{contact_id}"
98
+ end
45
99
  Resend::Request.new(path, {}, "delete").perform
46
100
  end
47
101
 
@@ -51,10 +105,18 @@ module Resend
51
105
  # @param params [Hash] the contact params
52
106
  # https://resend.com/docs/api-reference/contacts/update-contact
53
107
  def update(params)
54
- raise ArgumentError, "id or email is required" if params[:id].nil? && params[:email].nil?
108
+ raise ArgumentError, "Missing `id` or `email` field" if params[:id].nil? && params[:email].nil?
55
109
 
56
- path = "audiences/#{params[:audience_id]}/contacts/#{params[:id] || params[:email]}"
57
- Resend::Request.new(path, params, "patch").perform
110
+ contact_id = params[:id] || params[:email]
111
+ if params[:audience_id]
112
+ path = "audiences/#{params[:audience_id]}/contacts/#{contact_id}"
113
+ # Audience-scoped contacts don't support properties
114
+ payload = params.reject { |key, _| key == :properties }
115
+ else
116
+ path = "contacts/#{contact_id}"
117
+ payload = params
118
+ end
119
+ Resend::Request.new(path, payload, "patch").perform
58
120
  end
59
121
  end
60
122
  end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resend
4
+ module Emails
5
+ # Module for sent email attachments API operations
6
+ module Attachments
7
+ class << self
8
+ # Retrieve a single attachment from a sent email
9
+ #
10
+ # @param params [Hash] Parameters for retrieving the attachment
11
+ # @option params [String] :id The attachment ID (required)
12
+ # @option params [String] :email_id The email ID (required)
13
+ # @return [Hash] The attachment object
14
+ #
15
+ # @example
16
+ # Resend::Emails::Attachments.get(
17
+ # id: "2a0c9ce0-3112-4728-976e-47ddcd16a318",
18
+ # email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c"
19
+ # )
20
+ def get(params = {})
21
+ attachment_id = params[:id]
22
+ email_id = params[:email_id]
23
+
24
+ path = "emails/#{email_id}/attachments/#{attachment_id}"
25
+ Resend::Request.new(path, {}, "get").perform
26
+ end
27
+
28
+ # List attachments from a sent email with optional pagination
29
+ #
30
+ # @param params [Hash] Parameters for listing attachments
31
+ # @option params [String] :email_id The email ID (required)
32
+ # @option params [Integer] :limit Maximum number of attachments to return (1-100)
33
+ # @option params [String] :after Cursor for pagination (newer attachments)
34
+ # @option params [String] :before Cursor for pagination (older attachments)
35
+ # @return [Hash] List of attachments with pagination info
36
+ #
37
+ # @example List all attachments
38
+ # Resend::Emails::Attachments.list(
39
+ # email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c"
40
+ # )
41
+ #
42
+ # @example List with custom limit
43
+ # Resend::Emails::Attachments.list(
44
+ # email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
45
+ # limit: 50
46
+ # )
47
+ #
48
+ # @example List with pagination
49
+ # Resend::Emails::Attachments.list(
50
+ # email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
51
+ # limit: 20,
52
+ # after: "attachment_id_123"
53
+ # )
54
+ def list(params = {})
55
+ email_id = params[:email_id]
56
+ base_path = "emails/#{email_id}/attachments"
57
+
58
+ # Extract pagination parameters
59
+ pagination_params = params.slice(:limit, :after, :before)
60
+
61
+ path = Resend::PaginationHelper.build_paginated_path(base_path, pagination_params)
62
+ Resend::Request.new(path, {}, "get").perform
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resend
4
+ module Emails
5
+ module Receiving
6
+ # Module for received email attachments API operations
7
+ module Attachments
8
+ class << self
9
+ # Retrieve a single attachment from a received email
10
+ #
11
+ # @param params [Hash] Parameters for retrieving the attachment
12
+ # @option params [String] :id The attachment ID (required)
13
+ # @option params [String] :email_id The email ID (required)
14
+ # @return [Hash] The attachment object
15
+ #
16
+ # @example
17
+ # Resend::Emails::Receiving::Attachments.get(
18
+ # id: "2a0c9ce0-3112-4728-976e-47ddcd16a318",
19
+ # email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c"
20
+ # )
21
+ def get(params = {})
22
+ attachment_id = params[:id]
23
+ email_id = params[:email_id]
24
+
25
+ path = "emails/receiving/#{email_id}/attachments/#{attachment_id}"
26
+ Resend::Request.new(path, {}, "get").perform
27
+ end
28
+
29
+ # List attachments from a received email with optional pagination
30
+ #
31
+ # @param params [Hash] Parameters for listing attachments
32
+ # @option params [String] :email_id The email ID (required)
33
+ # @option params [Integer] :limit Maximum number of attachments to return (1-100)
34
+ # @option params [String] :after Cursor for pagination (newer attachments)
35
+ # @option params [String] :before Cursor for pagination (older attachments)
36
+ # @return [Hash] List of attachments with pagination info
37
+ #
38
+ # @example List all attachments
39
+ # Resend::Emails::Receiving::Attachments.list(
40
+ # email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c"
41
+ # )
42
+ #
43
+ # @example List with custom limit
44
+ # Resend::Emails::Receiving::Attachments.list(
45
+ # email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
46
+ # limit: 50
47
+ # )
48
+ #
49
+ # @example List with pagination
50
+ # Resend::Emails::Receiving::Attachments.list(
51
+ # email_id: "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
52
+ # limit: 20,
53
+ # after: "attachment_id_123"
54
+ # )
55
+ def list(params = {})
56
+ email_id = params[:email_id]
57
+ base_path = "emails/receiving/#{email_id}/attachments"
58
+
59
+ # Extract pagination parameters
60
+ pagination_params = params.slice(:limit, :after, :before)
61
+
62
+ path = Resend::PaginationHelper.build_paginated_path(base_path, pagination_params)
63
+ Resend::Request.new(path, {}, "get").perform
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resend
4
+ module Emails
5
+ # Module for receiving emails API operations
6
+ module Receiving
7
+ class << self
8
+ # Retrieve a single received email
9
+ #
10
+ # @param email_id [String] The ID of the received email
11
+ # @return [Hash] The received email object
12
+ #
13
+ # @example
14
+ # Resend::Emails::Receiving.get("4ef9a417-02e9-4d39-ad75-9611e0fcc33c")
15
+ def get(email_id = "")
16
+ path = "emails/receiving/#{email_id}"
17
+ Resend::Request.new(path, {}, "get").perform
18
+ end
19
+
20
+ # List received emails with optional pagination
21
+ #
22
+ # @param params [Hash] Optional parameters for pagination
23
+ # @option params [Integer] :limit Maximum number of emails to return (1-100)
24
+ # @option params [String] :after Cursor for pagination (newer emails)
25
+ # @option params [String] :before Cursor for pagination (older emails)
26
+ # @return [Hash] List of received emails with pagination info
27
+ #
28
+ # @example List all received emails
29
+ # Resend::Emails::Receiving.list
30
+ #
31
+ # @example List with custom limit
32
+ # Resend::Emails::Receiving.list(limit: 50)
33
+ #
34
+ # @example List with pagination
35
+ # Resend::Emails::Receiving.list(limit: 20, after: "email_id_123")
36
+ def list(params = {})
37
+ path = Resend::PaginationHelper.build_paginated_path("emails/receiving", params)
38
+ Resend::Request.new(path, {}, "get").perform
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
data/lib/resend/emails.rb CHANGED
@@ -51,12 +51,5 @@ module Resend
51
51
  Resend::Request.new(path, query_params, "get").perform
52
52
  end
53
53
  end
54
-
55
- # This method is kept here for backwards compatibility
56
- # Use Resend::Emails.send instead.
57
- def send_email(params)
58
- warn "[DEPRECATION] `send_email` is deprecated. Please use `Resend::Emails.send` instead."
59
- Resend::Emails.send(params)
60
- end
61
54
  end
62
55
  end
data/lib/resend/mailer.rb CHANGED
@@ -14,7 +14,7 @@ module Resend
14
14
  cc bcc
15
15
  from reply-to to subject mime-version
16
16
  html text
17
- content-type tags scheduled_at
17
+ content-type content-transfer-encoding tags scheduled_at
18
18
  headers options
19
19
  ].freeze
20
20
 
@@ -34,13 +34,16 @@ module Resend
34
34
  resp = HTTParty.send(@verb.to_sym, "#{BASE_URL}#{@path}", options)
35
35
 
36
36
  check_json!(resp)
37
- process_response(resp)
37
+ data = process_response(resp)
38
+ headers = extract_headers(resp)
39
+
40
+ Resend::Response.new(data, headers)
38
41
  end
39
42
 
40
- def handle_error!(resp)
41
- code = resp[:statusCode]
42
- body = resp[:message]
43
- headers = resp.respond_to?(:headers) ? resp.headers : (resp[:headers] || {})
43
+ def handle_error!(data, resp = nil)
44
+ code = data[:statusCode]
45
+ body = data[:message]
46
+ headers = resp.respond_to?(:headers) ? resp.headers : (data[:headers] || {})
44
47
 
45
48
  # get error from the known list of errors
46
49
  error_class = Resend::Error::ERRORS[code] || Resend::Error
@@ -66,20 +69,23 @@ module Resend
66
69
  end
67
70
 
68
71
  def process_response(resp)
69
- resp.transform_keys!(&:to_sym) unless resp.body.empty?
70
- handle_error!(resp) if error_response?(resp)
71
- resp
72
+ # Extract the parsed data from HTTParty response or use the hash directly (for tests/mocks)
73
+ data = resp.respond_to?(:parsed_response) ? resp.parsed_response : resp
74
+ data ||= {}
75
+ data.transform_keys!(&:to_sym) unless resp.body.empty?
76
+ handle_error!(data, resp) if error_response?(data)
77
+ data
72
78
  end
73
79
 
74
80
  def error_response?(resp)
75
- resp[:statusCode] && (resp[:statusCode] != 200 && resp[:statusCode] != 201)
81
+ resp[:statusCode] && resp[:statusCode] != 200 && resp[:statusCode] != 201
76
82
  end
77
83
 
78
84
  def set_idempotency_key
79
85
  # Only set idempotency key if the verb is POST for now.
80
86
  #
81
87
  # Does not set it if the idempotency_key is nil or empty
82
- if @verb.downcase == "post" && (!@options[:idempotency_key].nil? && !@options[:idempotency_key].empty?)
88
+ if @verb.downcase == "post" && !@options[:idempotency_key].nil? && !@options[:idempotency_key].empty?
83
89
  @headers["Idempotency-Key"] = @options[:idempotency_key]
84
90
  end
85
91
  end
@@ -101,5 +107,12 @@ module Resend
101
107
  rescue JSON::ParserError, TypeError
102
108
  raise Resend::Error::InternalServerError.new("Resend API returned an unexpected response", nil)
103
109
  end
110
+
111
+ # Extract and normalize headers from the HTTParty response
112
+ def extract_headers(resp)
113
+ return {} unless resp.respond_to?(:headers)
114
+
115
+ resp.headers.to_h.transform_keys { |k| k.to_s.downcase }
116
+ end
104
117
  end
105
118
  end
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resend
4
+ # Response wrapper that maintains backwards compatibility while exposing headers
5
+ #
6
+ # This class wraps API responses and behaves like a Hash for backwards compatibility,
7
+ # while also providing access to response headers via the #headers method.
8
+ #
9
+ # @example Backwards compatible hash access
10
+ # response = Resend::Emails.send(params)
11
+ # response[:id] # => "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794"
12
+ #
13
+ # @example Accessing response headers
14
+ # response = Resend::Emails.send(params)
15
+ # response.headers # => {"content-type" => "application/json", ...}
16
+ # response.headers['x-ratelimit-remaining'] # => "50"
17
+ class Response
18
+ include Enumerable
19
+
20
+ # @param data [Hash] The response data
21
+ # @param headers [Hash, HTTParty::Response] The response headers
22
+ def initialize(data, headers)
23
+ @data = data.is_a?(Hash) ? data : {}
24
+ @headers = normalize_headers(headers)
25
+ end
26
+
27
+ # Access response headers
28
+ # @return [Hash] Response headers as a hash with lowercase string keys
29
+ attr_reader :headers
30
+
31
+ # Hash-like access via []
32
+ # @param key [Symbol, String] The key to access
33
+ # @return [Object] The value at the key
34
+ def [](key)
35
+ @data[key]
36
+ end
37
+
38
+ # Hash-like assignment via []=
39
+ # @param key [Symbol, String] The key to set
40
+ # @param value [Object] The value to set
41
+ def []=(key, value)
42
+ @data[key] = value
43
+ end
44
+
45
+ # Dig into nested hash structure
46
+ # @param keys [Array<Symbol, String>] Keys to dig through
47
+ # @return [Object] The value at the nested key path
48
+ def dig(*keys)
49
+ @data.dig(*keys)
50
+ end
51
+
52
+ # Convert to plain hash
53
+ # @return [Hash] The underlying data hash
54
+ def to_h
55
+ @data
56
+ end
57
+
58
+ alias to_hash to_h
59
+
60
+ # Get all keys from the data
61
+ # @return [Array] Array of keys
62
+ def keys
63
+ @data.keys
64
+ end
65
+
66
+ # Get all values from the data
67
+ # @return [Array] Array of values
68
+ def values
69
+ @data.values
70
+ end
71
+
72
+ # Check if key exists
73
+ # @param key [Symbol, String] The key to check
74
+ # @return [Boolean] True if key exists
75
+ def key?(key)
76
+ @data.key?(key)
77
+ end
78
+
79
+ alias has_key? key?
80
+
81
+ # Enable enumeration over the data
82
+ def each(&block)
83
+ @data.each(&block)
84
+ end
85
+
86
+ # Transform keys in the underlying data
87
+ # @return [Resend::Response] Self for chaining
88
+ def transform_keys!(&block)
89
+ @data.transform_keys!(&block)
90
+ self
91
+ end
92
+
93
+ # Check if response is empty
94
+ # @return [Boolean] True if data is empty
95
+ def empty?
96
+ @data.empty?
97
+ end
98
+
99
+ # Respond to hash-like methods
100
+ def respond_to_missing?(method_name, include_private = false)
101
+ @data.respond_to?(method_name) || super
102
+ end
103
+
104
+ # Delegate unknown methods to the underlying data hash
105
+ def method_missing(method_name, *args, &block)
106
+ if @data.respond_to?(method_name)
107
+ result = @data.send(method_name, *args, &block)
108
+ # If the method returns the hash itself, return self to maintain wrapper
109
+ result.equal?(@data) ? self : result
110
+ else
111
+ super
112
+ end
113
+ end
114
+
115
+ # String representation for debugging
116
+ # @return [String] String representation of the response
117
+ def inspect
118
+ "#<Resend::Response data=#{@data.inspect} headers=#{@headers.keys.inspect}>"
119
+ end
120
+
121
+ private
122
+
123
+ # Normalize headers to a simple hash with lowercase string keys
124
+ # @param headers [Hash, HTTParty::Response, nil] The headers to normalize
125
+ # @return [Hash] Normalized headers hash
126
+ def normalize_headers(headers)
127
+ return {} if headers.nil?
128
+
129
+ # Handle HTTParty::Response object
130
+ headers = headers.headers if headers.respond_to?(:headers)
131
+
132
+ # Convert to hash and normalize keys to lowercase strings
133
+ case headers
134
+ when Hash
135
+ headers.to_h.transform_keys { |k| k.to_s.downcase }
136
+ else
137
+ {}
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resend
4
+ # Segments api wrapper
5
+ module Segments
6
+ class << self
7
+ # https://resend.com/docs/api-reference/segments/create-segment
8
+ def create(params)
9
+ path = "segments"
10
+ Resend::Request.new(path, params, "post").perform
11
+ end
12
+
13
+ # https://resend.com/docs/api-reference/segments/get-segment
14
+ def get(segment_id = "")
15
+ path = "segments/#{segment_id}"
16
+ Resend::Request.new(path, {}, "get").perform
17
+ end
18
+
19
+ # https://resend.com/docs/api-reference/segments/list-segments
20
+ def list(params = {})
21
+ path = Resend::PaginationHelper.build_paginated_path("segments", params)
22
+ Resend::Request.new(path, {}, "get").perform
23
+ end
24
+
25
+ # https://resend.com/docs/api-reference/segments/delete-segment
26
+ def remove(segment_id = "")
27
+ path = "segments/#{segment_id}"
28
+ Resend::Request.new(path, {}, "delete").perform
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resend
4
+ # Templates api wrapper
5
+ module Templates
6
+ class << self
7
+ # https://resend.com/docs/api-reference/templates/create-template
8
+ def create(params = {})
9
+ path = "templates"
10
+ Resend::Request.new(path, params, "post").perform
11
+ end
12
+
13
+ # https://resend.com/docs/api-reference/templates/get-template
14
+ def get(template_id = "")
15
+ path = "templates/#{template_id}"
16
+ Resend::Request.new(path, {}, "get").perform
17
+ end
18
+
19
+ # https://resend.com/docs/api-reference/templates/update-template
20
+ def update(template_id, params = {})
21
+ path = "templates/#{template_id}"
22
+ Resend::Request.new(path, params, "patch").perform
23
+ end
24
+
25
+ # https://resend.com/docs/api-reference/templates/publish-template
26
+ def publish(template_id = "")
27
+ path = "templates/#{template_id}/publish"
28
+ Resend::Request.new(path, {}, "post").perform
29
+ end
30
+
31
+ # https://resend.com/docs/api-reference/templates/duplicate-template
32
+ def duplicate(template_id = "")
33
+ path = "templates/#{template_id}/duplicate"
34
+ Resend::Request.new(path, {}, "post").perform
35
+ end
36
+
37
+ # https://resend.com/docs/api-reference/templates/list-templates
38
+ def list(params = {})
39
+ path = Resend::PaginationHelper.build_paginated_path("templates", params)
40
+ Resend::Request.new(path, {}, "get").perform
41
+ end
42
+
43
+ # https://resend.com/docs/api-reference/templates/delete-template
44
+ def remove(template_id = "")
45
+ path = "templates/#{template_id}"
46
+ Resend::Request.new(path, {}, "delete").perform
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resend
4
+ # Topics api wrapper
5
+ module Topics
6
+ class << self
7
+ # https://resend.com/docs/api-reference/topics/create-topic
8
+ def create(params = {})
9
+ path = "topics"
10
+ Resend::Request.new(path, params, "post").perform
11
+ end
12
+
13
+ # https://resend.com/docs/api-reference/topics/get-topic
14
+ def get(topic_id = "")
15
+ path = "topics/#{topic_id}"
16
+ Resend::Request.new(path, {}, "get").perform
17
+ end
18
+
19
+ # https://resend.com/docs/api-reference/topics/update-topic
20
+ def update(params = {})
21
+ path = "topics/#{params[:topic_id]}"
22
+ Resend::Request.new(path, params, "patch").perform
23
+ end
24
+
25
+ # https://resend.com/docs/api-reference/topics/list-topics
26
+ def list(params = {})
27
+ path = Resend::PaginationHelper.build_paginated_path("topics", params)
28
+ Resend::Request.new(path, {}, "get").perform
29
+ end
30
+
31
+ # https://resend.com/docs/api-reference/topics/delete-topic
32
+ def remove(topic_id = "")
33
+ path = "topics/#{topic_id}"
34
+ Resend::Request.new(path, {}, "delete").perform
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Resend
4
- VERSION = "0.27.0"
4
+ VERSION = "1.0.1"
5
5
  end
data/lib/resend.rb CHANGED
@@ -8,18 +8,27 @@ require "httparty"
8
8
  require "json"
9
9
  require "cgi"
10
10
  require "resend/errors"
11
+ require "resend/response"
11
12
  require "resend/client"
12
13
  require "resend/request"
13
14
  require "resend/pagination_helper"
14
15
 
15
16
  # API Operations
16
- require "resend/audiences"
17
+ require "resend/segments"
17
18
  require "resend/api_keys"
18
19
  require "resend/broadcasts"
19
20
  require "resend/batch"
20
21
  require "resend/contacts"
22
+ require "resend/contacts/segments"
23
+ require "resend/contacts/topics"
24
+ require "resend/contact_properties"
21
25
  require "resend/domains"
22
26
  require "resend/emails"
27
+ require "resend/templates"
28
+ require "resend/emails/receiving"
29
+ require "resend/emails/attachments"
30
+ require "resend/emails/receiving/attachments"
31
+ require "resend/topics"
23
32
  require "resend/webhooks"
24
33
 
25
34
  # Rails
@@ -36,4 +45,7 @@ module Resend
36
45
  end
37
46
  alias config configure
38
47
  end
48
+
49
+ # @deprecated Use Segments instead
50
+ Audiences = Segments
39
51
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resend
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Derich Pacheco
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-10-29 00:00:00.000000000 Z
11
+ date: 2026-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -38,34 +38,44 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- description:
41
+ description:
42
42
  email: carlosderich@gmail.com
43
43
  executables: []
44
44
  extensions: []
45
45
  extra_rdoc_files: []
46
46
  files:
47
+ - CHANGELOG.md
47
48
  - README.md
48
49
  - lib/resend.rb
49
50
  - lib/resend/api_keys.rb
50
- - lib/resend/audiences.rb
51
51
  - lib/resend/batch.rb
52
52
  - lib/resend/broadcasts.rb
53
53
  - lib/resend/client.rb
54
+ - lib/resend/contact_properties.rb
54
55
  - lib/resend/contacts.rb
56
+ - lib/resend/contacts/segments.rb
57
+ - lib/resend/contacts/topics.rb
55
58
  - lib/resend/domains.rb
56
59
  - lib/resend/emails.rb
60
+ - lib/resend/emails/attachments.rb
61
+ - lib/resend/emails/receiving.rb
62
+ - lib/resend/emails/receiving/attachments.rb
57
63
  - lib/resend/errors.rb
58
64
  - lib/resend/mailer.rb
59
65
  - lib/resend/pagination_helper.rb
60
66
  - lib/resend/railtie.rb
61
67
  - lib/resend/request.rb
68
+ - lib/resend/response.rb
69
+ - lib/resend/segments.rb
70
+ - lib/resend/templates.rb
71
+ - lib/resend/topics.rb
62
72
  - lib/resend/version.rb
63
73
  - lib/resend/webhooks.rb
64
74
  homepage: https://github.com/resend/resend-ruby
65
75
  licenses:
66
76
  - MIT
67
77
  metadata: {}
68
- post_install_message:
78
+ post_install_message:
69
79
  rdoc_options: []
70
80
  require_paths:
71
81
  - lib
@@ -80,8 +90,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
90
  - !ruby/object:Gem::Version
81
91
  version: '0'
82
92
  requirements: []
83
- rubygems_version: 3.4.10
84
- signing_key:
93
+ rubygems_version: 3.0.3.1
94
+ signing_key:
85
95
  specification_version: 4
86
96
  summary: The Ruby and Rails SDK for resend.com
87
97
  test_files: []
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Resend
4
- # Audiences api wrapper
5
- module Audiences
6
- class << self
7
- # https://resend.com/docs/api-reference/audiences/create-audience
8
- def create(params)
9
- path = "audiences"
10
- Resend::Request.new(path, params, "post").perform
11
- end
12
-
13
- # https://resend.com/docs/api-reference/audiences/get-audience
14
- def get(audience_id = "")
15
- path = "audiences/#{audience_id}"
16
- Resend::Request.new(path, {}, "get").perform
17
- end
18
-
19
- # https://resend.com/docs/api-reference/audiences/list-audiences
20
- def list(params = {})
21
- path = Resend::PaginationHelper.build_paginated_path("audiences", params)
22
- Resend::Request.new(path, {}, "get").perform
23
- end
24
-
25
- # https://resend.com/docs/api-reference/audiences/delete-audience
26
- def remove(audience_id = "")
27
- path = "audiences/#{audience_id}"
28
- Resend::Request.new(path, {}, "delete").perform
29
- end
30
- end
31
- end
32
- end