Skip to content

feat(inboxes): add support for the Inboxes API - #251

Merged
dielduarte merged 15 commits into
mainfrom
feature/dev-2324-ruby-sdk-internal-squad-devtools
Oct 16, 2026
Merged

dielduarte merged 15 commits into
mainfrom
feature/dev-2324-ruby-sdk-internal-squad-devtools

Conversation

@felipefreitag

@felipefreitag felipefreitag commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Summary

Add the Inboxes API to the Ruby SDK. The PR covers the 26 routes under /inboxes. The names follow the Node SDK preview (resend.inboxes.*) and the nested modules of this SDK.

  • Resend::Inboxes: create, list, get, update, remove. get takes an inbox ID or an email address.
  • Resend::Inboxes::Agent: get, update.
  • Resend::Inboxes::Labels: list, create, update, remove.
  • Resend::Inboxes::Threads: list, search, get, update, remove. Array filters (folders, labels, from, to, cc, bcc) go out as one comma-separated value.
  • Resend::Inboxes::Threads::Emails: list, get, reply, forward. Reply and forward accept attachments.
  • Resend::Inboxes::Drafts: list, create, get, update, remove, send. Create and update accept attachments. On update, attachments replaces every attachment on the draft, and [] removes them all.

Nested methods take one params hash with the path IDs (inbox_id, thread_id, email_id, label_id, draft_id). A missing path ID raises ArgumentError, as in Contacts::Segments. The other keys go to the API as they are, so nil clears a field where the API allows it.

Thread update accepts read, folder, add_label_ids and remove_label_ids. The API removed label_id, so the SDK does not document it.

Draft create, draft send, reply and forward take options: { idempotency_key: "..." }, the same way as Resend::Emails.send. The params hash then needs braces, as with Emails.send.

Reply, forward and draft send accept headers, a hash of string values, as on Resend::Emails.send. Draft send sends a body only when headers is set. In-Reply-To, References and Reply-To are reserved, and the API returns 422 for them.

The PR also adds examples/inboxes.rb and bumps the version to 1.18.0.

Depends on

  • The spec PR feat(inboxes): add the Inboxes API and webhook events to the spec resend-openapi#125.
  • monorepo #12396 (merged) for add_label_ids and remove_label_ids on thread update.
  • monorepo #12481 (merged) for draft attachments.
  • monorepo #12509 (merged) for custom headers on reply, forward and draft send.
  • monorepo #11768 (merged) for the Idempotency-Key header on draft create, draft send, reply and forward.
  • monorepo #12152 for the attachment IDs of sent thread emails. The SDK passes the response through, so no code depends on it.
  • The tone presets text merges after resend-monorepo #12580, #12634 and #12635 are deployed.

Verification

bundle install && bundle exec rubocop && bundle exec rake spec

Result: rubocop has no offenses. 466 examples, 0 failures.

End to end against https://api.resend.com with the shared test team, through the built code (bundle exec ruby -I lib e2e.rb). 39 calls, 0 failures.

  • Inboxes: list, get by ID, get by email address (upper case), update and restore. Create returns the expected 403 You have reached the inbox limit of your plan.
  • Agent: get, update and restore.
  • Labels: create with a lowercase color (returned as #E93D82), list, update, remove.
  • Threads: search by subject token, search with from, has_attachment and start_date, list with folders and read, list by labels, get, update read and folder, remove.
  • Thread labels: add_label_ids adds the label, remove_label_ids removes it, and the label still exists after. A body with the same ID in both arrays returns 422.
  • Thread emails: list, get, reply, reply with a base64 text attachment, forward to delivered@resend.dev.
  • Drafts: create with one attachment, get and list show it, update replaces it with two, update with [] empties it, send with one attachment. A second draft created and removed.

Idempotency: a draft created twice with one key gives one draft and idempotent-replayed: true. A draft sent twice with one key returns the same email id. The same key with a different body returns 409.

Headers: a reply with X-Ticket-Id goes to delivered@resend.dev. A draft sends with X-Ticket-Id. A reply with reply-to in headers returns 422.

examples/inboxes.rb also runs against the test inbox, with the inbox create and remove replaced by the existing inbox.

The e2e script removed every label, thread and draft it made. It is not in this PR.

Not in this PR

  • Webhook event types. The Ruby SDK has no typed webhook events, and Resend::Webhooks.verify works for the inbox.* events as it is.
  • Sender authentication fields. They are not on the API main branch.
  • README and CHANGELOG entries. The changelog is written at release time.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cubic analysis

7 issues found across 16 files

Confidence score: 4/5

  • examples/inboxes.rb only works for accounts that own acme.com and have receiving configured. Read the inbox address from configuration and reuse it in the get call.
  • The new inbox specs use should phrasing in their example descriptions, which violates the project’s test-naming rule. Reword the descriptions declaratively in the affected specs.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="spec/inboxes/drafts_spec.rb">

<violation number="1" location="spec/inboxes/drafts_spec.rb:22">
P3: Custom agent: **No `should` in tests**

All 10 `it` descriptions in this spec begin with "should" (e.g., "should list drafts with pagination"), which the No `should` in tests rule forbids. Rewrite them declaratively: "lists drafts with pagination", "raises when inbox_id is missing", "creates a reply draft", "retrieves a draft", "updates a draft and keeps explicit nils", "removes a draft", "sends a draft with no body".</violation>
</file>

<file name="spec/inboxes/threads_spec.rb">

<violation number="1" location="spec/inboxes/threads_spec.rb:20">
P2: Custom agent: **No `should` in tests**

All 11 `it` descriptions in this file start with "should" (lines 20, 32, 42, 48, 66, 72, 80, 88, 98, 107, 115), which the No `should` in tests rule flags. Reword them declaratively, e.g. "lists threads", "joins array filters with commas", "raises when inbox_id is missing", "searches threads", "retrieves a thread", "raises when thread_id is missing", "updates a thread with label changes", "sends the deprecated label_id", "removes a thread".</violation>
</file>

<file name="spec/inboxes/labels_spec.rb">

<violation number="1" location="spec/inboxes/labels_spec.rb:18">
P3: Custom agent: **No `should` in tests**

All seven `it` descriptions in this spec start with "should" (e.g. "should list labels", "should raise when label_id is missing"), which the No `should` in tests rule flags. Rewrite them declaratively: "lists labels", "raises when label_id is missing", "creates a label", "updates a label", "removes a label".</violation>
</file>

<file name="spec/inboxes/threads/emails_spec.rb">

<violation number="1" location="spec/inboxes/threads/emails_spec.rb:22">
P3: Custom agent: **No `should` in tests**

All eight `it` descriptions in this new spec use "should" phrasing. Per the project's "No `should` in tests" rule, descriptions must be declarative. Rename them, e.g. "lists thread emails with pagination", "raises when thread_id is missing", "retrieves a thread email", "raises when email_id is missing" (both), "replies with attachments", "forwards an email", and "raises when inbox_id is missing".</violation>
</file>

<file name="spec/inboxes_spec.rb">

<violation number="1" location="spec/inboxes_spec.rb:17">
P3: Custom agent: **No `should` in tests**

All 8 `it` descriptions in this file use "should" (e.g., `"should create an inbox"`, `"should list inboxes"`). Per the project's test-naming rule, use declarative phrasing instead: `it "creates an inbox"`, `it "lists inboxes"`, `it "passes pagination parameters"`, `it "retrieves an inbox by id"`, `it "encodes an email address"`, `it "updates an inbox"`, `it "raises when inbox_id is missing"`, `it "removes an inbox"`.</violation>
</file>

<file name="spec/inboxes/agent_spec.rb">

<violation number="1" location="spec/inboxes/agent_spec.rb:17">
P2: Custom agent: **No `should` in tests**

Four `it` descriptions in this new spec start with "should" (lines 17, 26, 32, 42), e.g. `it "should retrieve the agent settings"`. Per the no-`should`-in-tests rule, use declarative phrasing: "retrieves the agent settings", "raises when inbox_id is missing", "updates the agent settings and keeps explicit nils".</violation>
</file>

<file name="examples/inboxes.rb">

<violation number="1" location="examples/inboxes.rb:9">
P2: This example cannot create an inbox for accounts that do not own `acme.com` (and it also requires receiving to be configured). Read an inbox address from configuration and reuse it in the subsequent `get` call.</violation>
</file>

Linked issue analysis

Linked issue: DEV-2324: Ruby SDK (internal, squad-devtools)

Status Acceptance criteria Notes
⚠️ Add the Inboxes endpoints to the Ruby SDK The PR adds wrappers and specs for all 26 routes, but thread label updates still receive 422 until the upstream API change ships.

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

@@ -0,0 +1,121 @@
# frozen_string_literal: true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Custom agent: No should in tests

All 11 it descriptions in this file start with "should" (lines 20, 32, 42, 48, 66, 72, 80, 88, 98, 107, 115), which the No should in tests rule flags. Reword them declaratively, e.g. "lists threads", "joins array filters with commas", "raises when inbox_id is missing", "searches threads", "retrieves a thread", "raises when thread_id is missing", "updates a thread with label changes", "sends the deprecated label_id", "removes a thread".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At spec/inboxes/threads_spec.rb, line 20:

<comment>All 11 `it` descriptions in this file start with "should" (lines 20, 32, 42, 48, 66, 72, 80, 88, 98, 107, 115), which the No `should` in tests rule flags. Reword them declaratively, e.g. "lists threads", "joins array filters with commas", "raises when inbox_id is missing", "searches threads", "retrieves a thread", "raises when thread_id is missing", "updates a thread with label changes", "sends the deprecated label_id", "removes a thread".</comment>

<file context>
@@ -0,0 +1,121 @@
+  end
+
+  describe "list" do
+    it "should list threads" do
+      resp = {
+        object: "list",
</file context>

end

describe "get" do
it "should retrieve the agent settings" do

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Custom agent: No should in tests

Four it descriptions in this new spec start with "should" (lines 17, 26, 32, 42), e.g. it "should retrieve the agent settings". Per the no-should-in-tests rule, use declarative phrasing: "retrieves the agent settings", "raises when inbox_id is missing", "updates the agent settings and keeps explicit nils".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At spec/inboxes/agent_spec.rb, line 17:

<comment>Four `it` descriptions in this new spec start with "should" (lines 17, 26, 32, 42), e.g. `it "should retrieve the agent settings"`. Per the no-`should`-in-tests rule, use declarative phrasing: "retrieves the agent settings", "raises when inbox_id is missing", "updates the agent settings and keeps explicit nils".</comment>

<file context>
@@ -0,0 +1,46 @@
+  end
+
+  describe "get" do
+    it "should retrieve the agent settings" do
+      resp = { object: "inbox_agent", instructions: nil, tone: nil, enabled_actions: [] }
+      expect_request("inboxes/#{inbox_id}/agent", {}, "get", resp)
</file context>

Comment thread examples/inboxes.rb

Resend.api_key = ENV["RESEND_API_KEY"]

inbox = Resend::Inboxes.create({ email_address: "support@acme.com", name: "Customer Support" })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This example cannot create an inbox for accounts that do not own acme.com (and it also requires receiving to be configured). Read an inbox address from configuration and reuse it in the subsequent get call.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At examples/inboxes.rb, line 9:

<comment>This example cannot create an inbox for accounts that do not own `acme.com` (and it also requires receiving to be configured). Read an inbox address from configuration and reuse it in the subsequent `get` call.</comment>

<file context>
@@ -0,0 +1,63 @@
+
+Resend.api_key = ENV["RESEND_API_KEY"]
+
+inbox = Resend::Inboxes.create({ email_address: "support@acme.com", name: "Customer Support" })
+inbox_id = inbox[:id]
+puts "created inbox: #{inbox_id}"
</file context>

end

describe "list" do
it "should list drafts with pagination" do

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Custom agent: No should in tests

All 10 it descriptions in this spec begin with "should" (e.g., "should list drafts with pagination"), which the No should in tests rule forbids. Rewrite them declaratively: "lists drafts with pagination", "raises when inbox_id is missing", "creates a reply draft", "retrieves a draft", "updates a draft and keeps explicit nils", "removes a draft", "sends a draft with no body".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At spec/inboxes/drafts_spec.rb, line 22:

<comment>All 10 `it` descriptions in this spec begin with "should" (e.g., "should list drafts with pagination"), which the No `should` in tests rule forbids. Rewrite them declaratively: "lists drafts with pagination", "raises when inbox_id is missing", "creates a reply draft", "retrieves a draft", "updates a draft and keeps explicit nils", "removes a draft", "sends a draft with no body".</comment>

<file context>
@@ -0,0 +1,95 @@
+  end
+
+  describe "list" do
+    it "should list drafts with pagination" do
+      resp = { object: "list", has_more: false, data: [{ "id" => draft_id, "type" => "standalone", "snippet" => "Hi" }] }
+      expect_request("inboxes/#{inbox_id}/drafts?limit=10&before=#{draft_id}", {}, "get", resp)
</file context>

@@ -0,0 +1,75 @@
# frozen_string_literal: true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Custom agent: No should in tests

All seven it descriptions in this spec start with "should" (e.g. "should list labels", "should raise when label_id is missing"), which the No should in tests rule flags. Rewrite them declaratively: "lists labels", "raises when label_id is missing", "creates a label", "updates a label", "removes a label".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At spec/inboxes/labels_spec.rb, line 18:

<comment>All seven `it` descriptions in this spec start with "should" (e.g. "should list labels", "should raise when label_id is missing"), which the No `should` in tests rule flags. Rewrite them declaratively: "lists labels", "raises when label_id is missing", "creates a label", "updates a label", "removes a label".</comment>

<file context>
@@ -0,0 +1,75 @@
+  end
+
+  describe "list" do
+    it "should list labels" do
+      resp = {
+        object: "list",
</file context>

@@ -0,0 +1,90 @@
# frozen_string_literal: true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Custom agent: No should in tests

All eight it descriptions in this new spec use "should" phrasing. Per the project's "No should in tests" rule, descriptions must be declarative. Rename them, e.g. "lists thread emails with pagination", "raises when thread_id is missing", "retrieves a thread email", "raises when email_id is missing" (both), "replies with attachments", "forwards an email", and "raises when inbox_id is missing".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At spec/inboxes/threads/emails_spec.rb, line 22:

<comment>All eight `it` descriptions in this new spec use "should" phrasing. Per the project's "No `should` in tests" rule, descriptions must be declarative. Rename them, e.g. "lists thread emails with pagination", "raises when thread_id is missing", "retrieves a thread email", "raises when email_id is missing" (both), "replies with attachments", "forwards an email", and "raises when inbox_id is missing".</comment>

<file context>
@@ -0,0 +1,90 @@
+  end
+
+  describe "list" do
+    it "should list thread emails with pagination" do
+      resp = { object: "list", has_more: true, data: [{ "id" => email_id, "direction" => "inbound" }] }
+      expect_request("inboxes/#{inbox_id}/threads/#{thread_id}/emails?limit=1", {}, "get", resp)
</file context>

Comment thread spec/inboxes_spec.rb
end

describe "create" do
it "should create an inbox" do

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Custom agent: No should in tests

All 8 it descriptions in this file use "should" (e.g., "should create an inbox", "should list inboxes"). Per the project's test-naming rule, use declarative phrasing instead: it "creates an inbox", it "lists inboxes", it "passes pagination parameters", it "retrieves an inbox by id", it "encodes an email address", it "updates an inbox", it "raises when inbox_id is missing", it "removes an inbox".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At spec/inboxes_spec.rb, line 17:

<comment>All 8 `it` descriptions in this file use "should" (e.g., `"should create an inbox"`, `"should list inboxes"`). Per the project's test-naming rule, use declarative phrasing instead: `it "creates an inbox"`, `it "lists inboxes"`, `it "passes pagination parameters"`, `it "retrieves an inbox by id"`, `it "encodes an email address"`, `it "updates an inbox"`, `it "raises when inbox_id is missing"`, `it "removes an inbox"`.</comment>

<file context>
@@ -0,0 +1,95 @@
+  end
+
+  describe "create" do
+    it "should create an inbox" do
+      params = { email_address: "support@acme.com", name: "Customer Support", from_name: "Ada", forwarding: true }
+      expect_request("inboxes", params, "post", { object: "inbox", id: inbox_id })
</file context>
Suggested change
it "should create an inbox" do
it "creates an inbox" do

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Requires human review: Auto-approval blocked by 7 unresolved issues from previous reviews.

View guided diff | Re-trigger cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 existing issues remain and no new issues found across 5 files (changes from recent commits).

Confidence score: 5/5

  • The new test names in spec/inboxes/threads_spec.rb and spec/inboxes/drafts_spec.rb use “should,” which violates the test naming rule. Rename them with declarative descriptions.

Requires human review: Auto-approval blocked by 7 unresolved issues from previous reviews.

View guided diff | Re-trigger cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 5 files (changes from recent commits).

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Requires human review: Auto-approval blocked by 7 unresolved issues from previous reviews.

View guided diff | Re-trigger cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 existing issues remain and no new issues found across 4 files (changes from recent commits).

Confidence score: 5/5

  • The new test descriptions in spec/inboxes/threads/emails_spec.rb and spec/inboxes/drafts_spec.rb use “should,” contrary to the repository’s naming convention. Rename them declaratively.

Requires human review: Auto-approval blocked by 7 unresolved issues from previous reviews.

View guided diff | Re-trigger cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 existing issues remain and no new issues found across 4 files (changes from recent commits).

Confidence score: 5/5

  • The new test descriptions in spec/inboxes/threads/emails_spec.rb and spec/inboxes/drafts_spec.rb use “should,” which violates the repo’s test-naming rule. Rephrase them declaratively.

Requires human review: Auto-approval blocked by 7 unresolved issues from previous reviews.

View guided diff | Re-trigger cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Confidence score: 5/5

  • The @option type in lib/resend/inboxes/drafts.rb still excludes nil, so the generated API docs misrepresent the new claim. Include nil in the type.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="lib/resend/inboxes/drafts.rb">

<violation number="1" location="lib/resend/inboxes/drafts.rb:103">
P3: The option type still excludes `nil`, contradicting this new claim and misrepresenting the generated API docs. Update the `@option` type to include `nil`.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

# @option params [String, nil] :html the HTML body. Pass nil to clear
# @option params [String, nil] :text the plain text body. Pass nil to clear
# @option params [Array<Hash>] :attachments files to store on the draft, as in {create}. Sending
# the field replaces every attachment on the draft. Send [] or nil to remove them all

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The option type still excludes nil, contradicting this new claim and misrepresenting the generated API docs. Update the @option type to include nil.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At lib/resend/inboxes/drafts.rb, line 103:

<comment>The option type still excludes `nil`, contradicting this new claim and misrepresenting the generated API docs. Update the `@option` type to include `nil`.</comment>

<file context>
@@ -99,7 +100,7 @@ def get(params = {})
         # @option params [String, nil] :text the plain text body. Pass nil to clear
         # @option params [Array<Hash>] :attachments files to store on the draft, as in {create}. Sending
-        #   the field replaces every attachment on the draft. Send [] to remove them all
+        #   the field replaces every attachment on the draft. Send [] or nil to remove them all
         #
         # https://resend.com/docs/api-reference/inboxes/update-draft
</file context>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Requires human review: Auto-approval blocked by 8 unresolved issues from previous reviews.

View guided diff | Re-trigger cubic

@dielduarte dielduarte left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some findings so far in code, I tested locally and behavior wise is all good tho.

  • Attachment doc text: the doc comment on draft attachments, drafts.rb:52-54, says "a path or content_id returns a 422". The spec says a path without content returns a 422, and path is ignored when content is also sent.
  • Nits:
    • folders: [] is sent as folders=
    • the search tests don't cover the to, cc, bcc, labels and read filters
    • only draft send's test checks the Idempotency-Key header itself

Follow resend-openapi #137 and resend-node 7943103:

- Every inbox route takes the Inbox ID or the inbox email address.
  `Resend::Inboxes.path` encodes it once for every module.
- Agent: document `actions`, the `archive` and `move_to_trash` actions,
  and the four `tone` presets.
- Add `Resend::Inboxes::Threads::Labels` with `add`, `set` and
  `remove`. Thread update no longer documents `add_label_ids` or
  `remove_label_ids`.
- Reply and forward no longer cap attachments at 10 files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 existing issues remain and 3 new issues found across 13 files (changes from recent commits).

Confidence score: 4/5

  • In examples/inboxes.rb, the cleanup still calls the removed Threads.update API, so the example will fail. Use Threads::Labels.remove for cleanup.
  • In lib/resend.rb, the new Inboxes operations may require full-access API keys. Confirm production keys have the required permissions.
  • Several new test descriptions still use “should,” contrary to the project convention. Rename them declaratively in spec/inboxes/threads/labels_spec.rb, spec/inboxes/threads_spec.rb, spec/inboxes_spec.rb, and spec/inboxes/agent_spec.rb.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="examples/inboxes.rb">

<violation number="1" location="examples/inboxes.rb:34">
P2: The example adds the label through the new endpoint, but its later `Threads.update(... remove_label_ids: ...)` cleanup still uses the removed API and will fail. Replace that cleanup call with `Threads::Labels.remove`.</violation>
</file>

<file name="spec/inboxes/threads/labels_spec.rb">

<violation number="1" location="spec/inboxes/threads/labels_spec.rb:21">
P2: Custom agent: **No `should` in tests**

All nine `it` descriptions in this file start with "should" (e.g., "should add labels to a thread", "should raise when labels is missing"). Rename them declaratively per the project rule: "adds labels to a thread", "raises when labels is missing", "removes a label from a thread", etc.</violation>
</file>

<file name="lib/resend.rb">

<violation number="1" location="lib/resend.rb:50">
P2: Custom agent: **API Key Permission Check SDK Methods**

Please confirm production API keys have the permissions required by the new Inboxes operations; Resend restricts most of these endpoints to full-access keys.</violation>
</file>

Requires human review: Auto-approval blocked because this review re-detected 3 unresolved issues already reported by Cubic.

View guided diff | Re-trigger cubic

Comment thread examples/inboxes.rb

if (thread_id = threads[:data].first&.dig("id"))
Resend::Inboxes::Threads.update({ inbox_id: inbox_id, thread_id: thread_id, read: true })
thread_labels = Resend::Inboxes::Threads::Labels.add({ inbox_id: inbox_id, thread_id: thread_id, labels: [label[:id]] })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The example adds the label through the new endpoint, but its later Threads.update(... remove_label_ids: ...) cleanup still uses the removed API and will fail. Replace that cleanup call with Threads::Labels.remove.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At examples/inboxes.rb, line 34:

<comment>The example adds the label through the new endpoint, but its later `Threads.update(... remove_label_ids: ...)` cleanup still uses the removed API and will fail. Replace that cleanup call with `Threads::Labels.remove`.</comment>

<file context>
@@ -30,7 +30,9 @@
 if (thread_id = threads[:data].first&.dig("id"))
-  Resend::Inboxes::Threads.update({ inbox_id: inbox_id, thread_id: thread_id, read: true, add_label_ids: [label[:id]] })
+  Resend::Inboxes::Threads.update({ inbox_id: inbox_id, thread_id: thread_id, read: true })
+  thread_labels = Resend::Inboxes::Threads::Labels.add({ inbox_id: inbox_id, thread_id: thread_id, labels: [label[:id]] })
+  puts "thread labels: #{thread_labels[:data].length}"
 
</file context>

end

describe "add" do
it "should add labels to a thread" do

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Custom agent: No should in tests

All nine it descriptions in this file start with "should" (e.g., "should add labels to a thread", "should raise when labels is missing"). Rename them declaratively per the project rule: "adds labels to a thread", "raises when labels is missing", "removes a label from a thread", etc.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At spec/inboxes/threads/labels_spec.rb, line 21:

<comment>All nine `it` descriptions in this file start with "should" (e.g., "should add labels to a thread", "should raise when labels is missing"). Rename them declaratively per the project rule: "adds labels to a thread", "raises when labels is missing", "removes a label from a thread", etc.</comment>

<file context>
@@ -0,0 +1,83 @@
+  end
+
+  describe "add" do
+    it "should add labels to a thread" do
+      expect_request(labels_path, { labels: [label_id] }, "post", label_list)
+
</file context>
Suggested change
it "should add labels to a thread" do
it "adds labels to a thread" do

Comment thread lib/resend.rb
require "resend/inboxes/labels"
require "resend/inboxes/threads"
require "resend/inboxes/threads/emails"
require "resend/inboxes/threads/labels"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Custom agent: API Key Permission Check SDK Methods

Please confirm production API keys have the permissions required by the new Inboxes operations; Resend restricts most of these endpoints to full-access keys.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At lib/resend.rb, line 50:

<comment>Please confirm production API keys have the permissions required by the new Inboxes operations; Resend restricts most of these endpoints to full-access keys.</comment>

<file context>
@@ -47,6 +47,7 @@
 require "resend/inboxes/labels"
 require "resend/inboxes/threads"
 require "resend/inboxes/threads/emails"
+require "resend/inboxes/threads/labels"
 require "resend/inboxes/drafts"
 
</file context>

@dielduarte
dielduarte marked this pull request as ready for review October 16, 2026 20:01
@dielduarte
dielduarte merged commit 457837e into main Oct 16, 2026
8 checks passed
@dielduarte
dielduarte deleted the feature/dev-2324-ruby-sdk-internal-squad-devtools branch October 16, 2026 20:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants