Skip to content

Commit e81d874

Browse files
committed
feat(automations,events): add Automations and Events API namespaces
- Add Resend::Automations with create, get, update, remove, stop, list - Add Resend::Automations::Runs with list and get (nested namespace) - Add Resend::Events with create, get, update, remove, send, list - Add specs and examples for both namespaces - Add base64 as explicit runtime dependency (removed from Ruby 3.4 stdlib) - Move rails to Gemfile development group, remove from gemspec - Update Dockerfile to bundle install --without development
1 parent 3411354 commit e81d874

8 files changed

Lines changed: 852 additions & 0 deletions

File tree

examples/automations.rb

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# frozen_string_literal: true
2+
3+
require_relative "../lib/resend"
4+
5+
raise if ENV["RESEND_API_KEY"].nil?
6+
7+
Resend.api_key = ENV["RESEND_API_KEY"]
8+
9+
# 1. Create a template (needed for the send_email step config)
10+
template = Resend::Templates.create({
11+
name: "Welcome Email",
12+
from: "onboarding@resend.dev",
13+
subject: "Welcome!",
14+
html: "<p>Welcome to our platform!</p>"
15+
})
16+
template_id = template[:id]
17+
puts "created template: #{template_id}"
18+
19+
Resend::Templates.publish(template_id)
20+
puts "published template: #{template_id}"
21+
22+
# 2. Create a simple automation: trigger → send_email
23+
simple_automation = Resend::Automations.create({
24+
name: "Simple Welcome Automation",
25+
steps: [
26+
{
27+
key: "trigger",
28+
type: "trigger",
29+
config: { event_name: "user.created" }
30+
},
31+
{
32+
key: "send_welcome",
33+
type: "send_email",
34+
config: { template: { id: template_id } }
35+
}
36+
],
37+
connections: [
38+
{ from: "trigger", to: "send_welcome", type: "default" }
39+
]
40+
})
41+
automation_id = simple_automation[:id]
42+
puts "created simple automation: #{automation_id}"
43+
44+
# 3. Get automation
45+
retrieved = Resend::Automations.get(automation_id)
46+
puts "retrieved automation: #{retrieved[:id]}, status: #{retrieved[:status]}"
47+
48+
# 4. Update automation (change status to enabled)
49+
updated = Resend::Automations.update({
50+
automation_id: automation_id,
51+
status: "enabled"
52+
})
53+
puts "updated automation: #{updated[:id]}"
54+
55+
# 5. List automations (without filter)
56+
all_automations = Resend::Automations.list
57+
puts "automations: #{all_automations[:data].length}, has_more: #{all_automations[:has_more]}"
58+
59+
# List automations with status filter
60+
enabled_automations = Resend::Automations.list({ status: "enabled" })
61+
puts "enabled automations: #{enabled_automations[:data].length}"
62+
63+
# 6. Stop automation
64+
stopped = Resend::Automations.stop(automation_id)
65+
puts "stopped automation: #{stopped[:id]}"
66+
67+
# 7. List runs (Resend::Automations::Runs.list)
68+
runs = Resend::Automations::Runs.list(automation_id)
69+
puts "runs: #{runs[:data].length}, has_more: #{runs[:has_more]}"
70+
71+
# 8. Get a run if any exist (Resend::Automations::Runs.get)
72+
if runs[:data].any?
73+
run_id = runs[:data].first[:id]
74+
run = Resend::Automations::Runs.get(automation_id, run_id)
75+
puts "run: #{run[:id]}, status: #{run[:status]}"
76+
else
77+
puts "no runs yet for this automation"
78+
end
79+
80+
# 9. Multi-step automation: trigger → delay → wait_for_event → send_email
81+
multi_automation = Resend::Automations.create({
82+
name: "Multi-step Onboarding Automation",
83+
steps: [
84+
{
85+
key: "trigger",
86+
type: "trigger",
87+
config: { event_name: "user.created" }
88+
},
89+
{
90+
key: "wait_30_min",
91+
type: "delay",
92+
config: { duration: "30 minutes" }
93+
},
94+
{
95+
key: "wait_verified",
96+
type: "wait_for_event",
97+
config: { event_name: "user.verified", timeout: "1 hour" }
98+
},
99+
{
100+
key: "send_welcome",
101+
type: "send_email",
102+
config: { template: { id: template_id } }
103+
}
104+
],
105+
connections: [
106+
{ from: "trigger", to: "wait_30_min", type: "default" },
107+
{ from: "wait_30_min", to: "wait_verified", type: "default" },
108+
{ from: "wait_verified", to: "send_welcome", type: "event_received" }
109+
]
110+
})
111+
multi_automation_id = multi_automation[:id]
112+
puts "created multi-step automation: #{multi_automation_id}"
113+
114+
# 10. Cleanup: delete both automations and the template
115+
Resend::Automations.remove(automation_id)
116+
puts "removed automation: #{automation_id}"
117+
118+
Resend::Automations.remove(multi_automation_id)
119+
puts "removed multi-step automation: #{multi_automation_id}"
120+
121+
Resend::Templates.remove(template_id)
122+
puts "removed template: #{template_id}"

examples/events.rb

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# frozen_string_literal: true
2+
3+
require_relative "../lib/resend"
4+
5+
raise if ENV["RESEND_API_KEY"].nil?
6+
7+
Resend.api_key = ENV["RESEND_API_KEY"]
8+
9+
# 1. Create a global contact (needed for event sends)
10+
contact = Resend::Contacts.create({
11+
email: "test.events@example.com",
12+
first_name: "Test",
13+
last_name: "User"
14+
})
15+
contact_id = contact[:id]
16+
puts "created contact: #{contact_id}"
17+
18+
# 2. Create event without schema
19+
event_no_schema = Resend::Events.create({ name: "user.signed_up" })
20+
puts "created event without schema: #{event_no_schema[:id]}"
21+
22+
# 3. Create event with schema
23+
schema = {
24+
"plan" => "string",
25+
"trial_days" => "number",
26+
"is_enterprise" => "boolean",
27+
"upgraded_at" => "date"
28+
}
29+
event_with_schema = Resend::Events.create({ name: "user.upgraded", schema: schema })
30+
event_id = event_with_schema[:id]
31+
puts "created event with schema: #{event_id}"
32+
33+
# 4. Get event by ID
34+
fetched_by_id = Resend::Events.get(event_id)
35+
puts "fetched event by ID: #{fetched_by_id[:id]}, name: #{fetched_by_id[:name]}"
36+
37+
# 5. Get event by name
38+
fetched_by_name = Resend::Events.get("user.upgraded")
39+
puts "fetched event by name: #{fetched_by_name[:id]}, name: #{fetched_by_name[:name]}"
40+
41+
# 6. Update event schema
42+
new_schema = {
43+
"plan" => "string",
44+
"trial_days" => "number",
45+
"is_enterprise" => "boolean",
46+
"upgraded_at" => "date",
47+
"referral_code" => "string"
48+
}
49+
updated_event = Resend::Events.update({ identifier: event_id, schema: new_schema })
50+
puts "updated event: #{updated_event[:id]}"
51+
52+
# 7. Send event with contact_id
53+
sent_with_contact_id = Resend::Events.send({
54+
event: "user.upgraded",
55+
contact_id: contact_id,
56+
payload: { plan: "pro", trial_days: 14, is_enterprise: false }
57+
})
58+
puts "sent event with contact_id: #{sent_with_contact_id[:event]}"
59+
60+
# 8. Send event with email
61+
sent_with_email = Resend::Events.send({
62+
event: "user.signed_up",
63+
email: "test.events@example.com"
64+
})
65+
puts "sent event with email: #{sent_with_email[:event]}"
66+
67+
# 9. List events
68+
events = Resend::Events.list
69+
puts "total events: #{events[:data].length}, has_more: #{events[:has_more]}"
70+
71+
# 10. List events with pagination params
72+
paginated = Resend::Events.list({ limit: 5 })
73+
puts "paginated events (limit 5): #{paginated[:data].length}"
74+
75+
if paginated[:has_more]
76+
last_id = paginated[:data].last[:id]
77+
more_events = Resend::Events.list({ limit: 5, after: last_id })
78+
puts "next page: #{more_events[:data].length}"
79+
end
80+
81+
# 11. Delete event by ID
82+
deleted_by_id = Resend::Events.remove(event_id)
83+
puts "deleted event by ID: #{deleted_by_id[:id]}, deleted: #{deleted_by_id[:deleted]}"
84+
85+
# 12. Delete event by name
86+
deleted_by_name = Resend::Events.remove("user.signed_up")
87+
puts "deleted event by name: #{deleted_by_name[:deleted]}"
88+
89+
# 13. Cleanup: delete contact
90+
Resend::Contacts.remove({ id: contact_id })
91+
puts "removed contact: #{contact_id}"

lib/resend.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
require "resend/logs"
3232
require "resend/topics"
3333
require "resend/webhooks"
34+
require "resend/automations"
35+
require "resend/automations/runs"
36+
require "resend/events"
3437

3538
# Rails
3639
require "resend/railtie" if defined?(Rails) && defined?(ActionMailer)

lib/resend/automations.rb

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# frozen_string_literal: true
2+
3+
module Resend
4+
# automations api wrapper
5+
module Automations
6+
class << self
7+
# https://resend.com/docs/api-reference/automations/create-automation
8+
def create(params = {})
9+
Resend::Request.new("automations", params, "post").perform
10+
end
11+
12+
# https://resend.com/docs/api-reference/automations/get-automation
13+
def get(automation_id = "")
14+
Resend::Request.new("automations/#{automation_id}", {}, "get").perform
15+
end
16+
17+
# https://resend.com/docs/api-reference/automations/update-automation
18+
def update(params = {})
19+
path = "automations/#{params[:automation_id]}"
20+
payload = params.reject { |k, _| k == :automation_id }
21+
Resend::Request.new(path, payload, "patch").perform
22+
end
23+
24+
# https://resend.com/docs/api-reference/automations/delete-automation
25+
def remove(automation_id = "")
26+
Resend::Request.new("automations/#{automation_id}", {}, "delete").perform
27+
end
28+
29+
# https://resend.com/docs/api-reference/automations/stop-automation
30+
def stop(automation_id = "")
31+
Resend::Request.new("automations/#{automation_id}/stop", {}, "post").perform
32+
end
33+
34+
# https://resend.com/docs/api-reference/automations/list-automations
35+
def list(params = {})
36+
path = Resend::PaginationHelper.build_paginated_path("automations", params)
37+
Resend::Request.new(path, {}, "get").perform
38+
end
39+
end
40+
end
41+
end

lib/resend/automations/runs.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# frozen_string_literal: true
2+
3+
module Resend
4+
module Automations
5+
# Automation Runs api wrapper
6+
module Runs
7+
class << self
8+
# https://resend.com/docs/api-reference/automations/list-automation-runs
9+
def list(automation_id, params = {})
10+
base_path = "automations/#{automation_id}/runs"
11+
path = Resend::PaginationHelper.build_paginated_path(base_path, params)
12+
Resend::Request.new(path, {}, "get").perform
13+
end
14+
15+
# https://resend.com/docs/api-reference/automations/get-automation-run
16+
def get(automation_id, run_id)
17+
Resend::Request.new("automations/#{automation_id}/runs/#{run_id}", {}, "get").perform
18+
end
19+
end
20+
end
21+
end
22+
end

lib/resend/events.rb

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# frozen_string_literal: true
2+
3+
module Resend
4+
# events api wrapper
5+
module Events
6+
class << self
7+
# https://resend.com/docs/api-reference/events/create-event
8+
def create(params = {})
9+
Resend::Request.new("events", params, "post").perform
10+
end
11+
12+
# https://resend.com/docs/api-reference/events/get-event
13+
# identifier can be a UUID or an event name (e.g. "user.signed_up")
14+
def get(identifier = "")
15+
path = "events/#{CGI.escape(identifier.to_s)}"
16+
Resend::Request.new(path, {}, "get").perform
17+
end
18+
19+
# https://resend.com/docs/api-reference/events/update-event
20+
def update(params = {})
21+
identifier = params[:identifier]
22+
path = "events/#{CGI.escape(identifier.to_s)}"
23+
payload = params.reject { |k, _| k == :identifier }
24+
Resend::Request.new(path, payload, "patch").perform
25+
end
26+
27+
# https://resend.com/docs/api-reference/events/delete-event
28+
# identifier can be a UUID or an event name (e.g. "user.signed_up")
29+
def remove(identifier = "")
30+
path = "events/#{CGI.escape(identifier.to_s)}"
31+
Resend::Request.new(path, {}, "delete").perform
32+
end
33+
34+
# https://resend.com/docs/api-reference/events/send-event
35+
def send(params = {})
36+
Resend::Request.new("events/send", params, "post").perform
37+
end
38+
39+
# https://resend.com/docs/api-reference/events/list-events
40+
def list(params = {})
41+
path = Resend::PaginationHelper.build_paginated_path("events", params)
42+
Resend::Request.new(path, {}, "get").perform
43+
end
44+
end
45+
end
46+
end

0 commit comments

Comments
 (0)