feat(inboxes): add the inboxes endpoints and inbox webhook events
Merged
FE
6d ago+3561+3561+0123456789012345678901234567890123456789-11-11-01234567890123456789
Summary
This PR adds the Inboxes API to the Rust SDK.
resend.inboxesis a newInboxesSvcwith the 29/inboxesoperations. The nested resources use flat, prefixed methods, the same aswebhooks.list_events:- Inboxes:
create,list,get,update,delete. - Agent:
get_agent,update_agent. - Labels:
list_labels,create_label,update_label,delete_label. - Threads:
list_threads,search_threads,get_thread,update_thread,delete_thread. - Thread labels:
add_thread_labels,set_thread_labels,remove_thread_label. - Thread emails:
list_thread_emails,get_thread_email,reply_thread_email,forward_thread_email. - Drafts:
list_drafts,create_draft,get_draft,update_draft,delete_draft,send_draft.
- Inboxes:
- The list endpoints take the usual
ListOptions<T>.list_threadsandsearch_threadsalso take a filter struct. The struct sendsfolders,labels,from,to,ccandbccas comma-separated values, as the API requires. - Create inbox, create label and create draft return
{ object, id }. Reply, forward and send draft return{ id }, the ID of the sent email. reply_thread_emailandforward_thread_emailaccept attachments. They useCreateAttachment, the same type asemails.send.- Every method takes the inbox ID or the inbox email address.
inbox_pathpercent-encodes it. update_threadtakesreadandfolder. The folder is anUpdateInboxThreadFolder, becausesentcannot be set. Labels change throughadd_thread_labels(POST, 1 to 10 IDs),set_thread_labels(PUT, up to 100 IDs, an empty slice clears them) andremove_thread_label(DELETE). Each returns aListInboxThreadLabelsResponsewith every label on the thread.- The agent uses
actions.InboxAgentActionhasArchiveandMoveToTrash, andtoneis theInboxAgentToneenum of the four presets. update_draftreturnsUpdateInboxDraftResponse, with onlyobjectandid.- Search results have no
highlights.matched_email_idis the emailidthatlist_thread_emailsreturns. Inboxhasupdated_at, andInboxListItemhascreated_atandupdated_at.- Drafts accept attachments (resend/monorepo#12481).
CreateInboxDraftAttachmentneedscontent,filenameandcontent_type, because the API stores each file on the draft. On update,with_attachmentsreplaces every attachment, and an empty list removes them all. Drafts, draft list items and the draft ininbox.draft.*events returnattachments. - Create draft, send draft, reply and forward accept an
Idempotency-Keyheader (resend/monorepo#11768). They expose it the same way asemails.send:with_idempotency_keyon the options returns anIdempotent<T>.send_drafttakes aSendInboxDraftOptionsfor this, because the request has no body. - Reply, forward and send draft accept custom
headers(resend/monorepo#12509), throughwith_headeras onemails.send. Resend setsIn-Reply-To,ReferencesandReply-To, so the API returns a 422 for them.send_draftsends a body only when headers are set. UpdateInboxAgentOptionsandUpdateInboxDraftOptionshaveclear_*methods that sendnull, because the API clears a field onnull.EventandEventTypeget the 14inbox.*webhook events.InboxEventis an enum tagged bytype, because thedatashape changes with the event type.events_up_to_datenow counts the inbox events instead of skipping them.- The doc comments use the words of the OpenAPI spec descriptions, from resend/resend-openapi#125 and #137.
- Version bump to
0.35.0, in its own commit. I leftCHANGELOG.mdfor the release.
Depends on
- No SDK release is needed. The API changes this PR follows (resend/monorepo#12396, #12481, #11768 and #12509) are live.
- The tone presets text merges after resend-monorepo #12580, #12634 and #12635 are deployed.
Verification
cargo buildcargo fmt --checkcargo clippy --all-targets -- -Dwarningscargo clippy --all-targets --no-default-features --features rustls-tls -- -Dwarningscargo clippy --all-targets --features blocking -- -Dwarningscargo test --lib inbox: 29 offline tests pass, with and without--features blocking. They cover the request bodies, the query strings, the response shapes, and one payload per inbox webhook event.cargo test --lib events_up_to_date: passes against the live event types page with the 14 inbox events counted.
The three clippy runs and cargo fmt --check pass.
A live run through the methods against https://api.resend.com, on a test inbox addressed by its email address. It restored every setting it changed and did not create or delete an inbox. All 33 checks passed:
get,updateandlist: OK.updated_atand the list itemcreated_atandupdated_atare set. The name was restored.get_agentandupdate_agentwithInboxAgentTone::ExpandedCasualand[Archive, MoveToTrash]: OK, and the old values were restored.create_label,update_label,list_labels,delete_label: OK.add_thread_labels,set_thread_labelswith an empty slice,remove_thread_label: OK, each returned the thread labels. Removing a label that is not on the thread returned 200. An unknown label returned 404Label not found.get_thread,update_threadwithreadand a restore,list_threads, anddelete_threadon a thread in trash, which returneddeleted: false.search_threads: OK, andmatched_email_idis an emailidfromlist_thread_emails.list_thread_emails,get_thread_email,reply_thread_email,forward_thread_email: OK.create_draft,update_draft(onlyobjectandid),get_draft,list_drafts,send_draft,delete_draft: OK.- An unknown inbox address returned 404
Inbox not found.
The crate tests that call the live API do not include inboxes, because the CI team may have no inbox to test with.
Not in this PR
- Sender authentication fields. They are not on the API yet.