From d354efdd7e78280228f90a73200ceec392ee5c49 Mon Sep 17 00:00:00 2001 From: drish Date: Tue, 31 Mar 2026 10:14:45 -0300 Subject: [PATCH 1/4] feat(logs): add logs API support Implements Resend::Logs.get and Resend::Logs.list endpoints. --- examples/logs.rb | 27 +++++++ lib/resend.rb | 1 + lib/resend/logs.rb | 20 ++++++ spec/logs_spec.rb | 176 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 224 insertions(+) create mode 100644 examples/logs.rb create mode 100644 lib/resend/logs.rb create mode 100644 spec/logs_spec.rb diff --git a/examples/logs.rb b/examples/logs.rb new file mode 100644 index 0000000..0aa7e61 --- /dev/null +++ b/examples/logs.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require_relative "../lib/resend" + +raise if ENV["RESEND_API_KEY"].nil? + +Resend.api_key = ENV["RESEND_API_KEY"] + +def get_log + log = Resend::Logs.get("3d4a472d-bc6d-4dd2-aa9d-d3d11b549e55") + puts log +end + +def list + logs = Resend::Logs.list + puts logs +end + +def list_paginated + logs = Resend::Logs.list({ limit: 10, after: "log_id_here" }) + puts logs + puts "Has more: #{logs[:has_more]}" if logs[:has_more] +end + +get_log +# list +# list_paginated diff --git a/lib/resend.rb b/lib/resend.rb index bceb00c..86faf80 100644 --- a/lib/resend.rb +++ b/lib/resend.rb @@ -28,6 +28,7 @@ require "resend/emails/receiving" require "resend/emails/attachments" require "resend/emails/receiving/attachments" +require "resend/logs" require "resend/topics" require "resend/webhooks" diff --git a/lib/resend/logs.rb b/lib/resend/logs.rb new file mode 100644 index 0000000..a8e9b31 --- /dev/null +++ b/lib/resend/logs.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Resend + # logs api wrapper + module Logs + class << self + # https://resend.com/docs/api-reference/logs/retrieve-log + def get(log_id = "") + path = "logs/#{log_id}" + Resend::Request.new(path, {}, "get").perform + end + + # https://resend.com/docs/api-reference/logs/list-logs + def list(params = {}) + path = Resend::PaginationHelper.build_paginated_path("logs", params) + Resend::Request.new(path, {}, "get").perform + end + end + end +end diff --git a/spec/logs_spec.rb b/spec/logs_spec.rb new file mode 100644 index 0000000..044ea12 --- /dev/null +++ b/spec/logs_spec.rb @@ -0,0 +1,176 @@ +# frozen_string_literal: true + +RSpec.describe "Logs" do + context "static api_key" do + before do + Resend.configure do |config| + config.api_key = "re_123" + end + end + + describe "get" do + it "should retrieve a log" do + resp = { + "object": "log", + "id": "3d4a472d-bc6d-4dd2-aa9d-d3d11b549e55", + "created_at": "2024-11-01T18:10:00.000Z", + "endpoint": "/emails", + "method": "POST", + "response_status": 200, + "user_agent": "resend-ruby:1.0.0", + "request_body": { "from": "user@example.com", "to": "recipient@example.com" }, + "response_body": { "id": "email_123" } + } + allow_any_instance_of(Resend::Request).to receive(:perform).and_return(resp) + result = Resend::Logs.get("3d4a472d-bc6d-4dd2-aa9d-d3d11b549e55") + expect(result[:id]).to eql("3d4a472d-bc6d-4dd2-aa9d-d3d11b549e55") + expect(result[:object]).to eql("log") + expect(result[:endpoint]).to eql("/emails") + expect(result[:method]).to eql("POST") + expect(result[:response_status]).to eql(200) + end + + it "should handle nullable user_agent" do + resp = { + "object": "log", + "id": "3d4a472d-bc6d-4dd2-aa9d-d3d11b549e55", + "created_at": "2024-11-01T18:10:00.000Z", + "endpoint": "/emails", + "method": "POST", + "response_status": 200, + "user_agent": nil, + "request_body": {}, + "response_body": {} + } + allow_any_instance_of(Resend::Request).to receive(:perform).and_return(resp) + result = Resend::Logs.get("3d4a472d-bc6d-4dd2-aa9d-d3d11b549e55") + expect(result[:user_agent]).to be_nil + end + + it "should raise when log is not found" do + resp = { + "statusCode" => 404, + "name" => "not_found", + "message" => "Log not found" + } + allow(resp).to receive(:body).and_return(resp) + allow(HTTParty).to receive(:send).and_return(resp) + expect { Resend::Logs.get("missing-id") }.to raise_error(Resend::Error::InvalidRequestError, /Log not found/) + end + + it "should raise when log_id is not a valid UUID" do + resp = { + "statusCode" => 422, + "name" => "validation_error", + "message" => "The `logId` must be a valid UUID." + } + allow(resp).to receive(:body).and_return(resp) + allow(HTTParty).to receive(:send).and_return(resp) + expect { Resend::Logs.get("not-a-uuid") }.to raise_error(Resend::Error::InvalidRequestError, /must be a valid UUID/) + end + end + + describe "list" do + it "should list logs" do + resp = { + "object": "list", + "has_more": false, + "data": [ + { + "id": "3d4a472d-bc6d-4dd2-aa9d-d3d11b549e55", + "created_at": "2024-11-01T18:10:00.000Z", + "endpoint": "/emails", + "method": "POST", + "response_status": 200, + "user_agent": "resend-ruby:1.0.0" + }, + { + "id": "4e5b583e-cd7e-5ee3-bbae-e4e22c650f66", + "created_at": "2024-11-01T17:00:00.000Z", + "endpoint": "/emails", + "method": "POST", + "response_status": 422, + "user_agent": nil + } + ] + } + allow_any_instance_of(Resend::Request).to receive(:perform).and_return(resp) + result = Resend::Logs.list + expect(result[:data].length).to eql(2) + expect(result[:has_more]).to eql(false) + expect(result[:data].first[:id]).to eql("3d4a472d-bc6d-4dd2-aa9d-d3d11b549e55") + expect(result[:data].last[:user_agent]).to be_nil + end + + it "should list logs with pagination params" do + resp = { + "object": "list", + "has_more": true, + "data": [ + { + "id": "3d4a472d-bc6d-4dd2-aa9d-d3d11b549e55", + "created_at": "2024-11-01T18:10:00.000Z", + "endpoint": "/emails", + "method": "POST", + "response_status": 200, + "user_agent": "resend-ruby:1.0.0" + } + ] + } + allow_any_instance_of(Resend::Request).to receive(:perform).and_return(resp) + result = Resend::Logs.list({ limit: 1 }) + expect(result[:data].length).to eql(1) + expect(result[:has_more]).to eql(true) + end + end + end + + context "dynamic api_key" do + before do + Resend.configure do |config| + config.api_key = -> { "re_123" } + end + end + + describe "get" do + it "should retrieve a log" do + resp = { + "object": "log", + "id": "3d4a472d-bc6d-4dd2-aa9d-d3d11b549e55", + "created_at": "2024-11-01T18:10:00.000Z", + "endpoint": "/emails", + "method": "POST", + "response_status": 200, + "user_agent": "resend-ruby:1.0.0", + "request_body": {}, + "response_body": {} + } + allow_any_instance_of(Resend::Request).to receive(:perform).and_return(resp) + result = Resend::Logs.get("3d4a472d-bc6d-4dd2-aa9d-d3d11b549e55") + expect(result[:id]).to eql("3d4a472d-bc6d-4dd2-aa9d-d3d11b549e55") + end + end + + describe "list" do + it "should list logs" do + resp = { + "object": "list", + "has_more": false, + "data": [ + { + "id": "3d4a472d-bc6d-4dd2-aa9d-d3d11b549e55", + "created_at": "2024-11-01T18:10:00.000Z", + "endpoint": "/emails", + "method": "POST", + "response_status": 200, + "user_agent": "resend-ruby:1.0.0" + } + ] + } + allow_any_instance_of(Resend::Request).to receive(:perform).and_return(resp) + result = Resend::Logs.list + expect(result[:data].length).to eql(1) + end + end + end +end From c74eca6bd411cb9e3bac66df85cc8eae8023db78 Mon Sep 17 00:00:00 2001 From: drish Date: Tue, 31 Mar 2026 10:21:25 -0300 Subject: [PATCH 2/4] chore: bump version to 1.1.0 --- lib/resend/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/resend/version.rb b/lib/resend/version.rb index 0d55157..c622638 100644 --- a/lib/resend/version.rb +++ b/lib/resend/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Resend - VERSION = "1.0.1" + VERSION = "1.1.0" end From a7b6db97559f86b76e4eb4b086c37efdf69588f6 Mon Sep 17 00:00:00 2001 From: drish Date: Wed, 1 Apr 2026 18:20:47 -0300 Subject: [PATCH 3/4] fix(logs): uncomment list and list_paginated example calls --- examples/logs.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/logs.rb b/examples/logs.rb index 0aa7e61..e273e31 100644 --- a/examples/logs.rb +++ b/examples/logs.rb @@ -23,5 +23,5 @@ def list_paginated end get_log -# list -# list_paginated +list +list_paginated From 62c200f98ac18f634ffeb56b450ce9de43474b53 Mon Sep 17 00:00:00 2001 From: drish Date: Wed, 1 Apr 2026 18:25:16 -0300 Subject: [PATCH 4/4] fix(logs): comment out list_paginated call with placeholder cursor --- examples/logs.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/logs.rb b/examples/logs.rb index e273e31..ef15696 100644 --- a/examples/logs.rb +++ b/examples/logs.rb @@ -24,4 +24,4 @@ def list_paginated get_log list -list_paginated +# list_paginated