Skip to content

Conversation

@lucasfcosta
Copy link
Contributor

@lucasfcosta lucasfcosta commented Oct 14, 2025

Before https://github.com/resend/resend-api/pull/2199 we were proxying contents directly through our API. For various reasons related to reliability and overall separation of concerns, we started using signed URLs as explained in the aforementioned PR.

This PR makes our SDK automatically download from those URLs and encode content as base64 so it can automatically be used by the resend.send method.

I'm also bumping the version here so we don't have to do a separate PR for that.


Summary by cubic

Switch SDK attachment downloads to API-provided signed URLs, then return base64 content to preserve the SDK response shape. Aligns with PRODUCT-796 by removing proxied content for better reliability.

  • New Features

    • get: fetches metadata with download_url, downloads file, returns base64 content.
    • list: downloads each attachment via signed URL and returns base64 content.
    • Types: API responses now include download_url; SDK responses still expose content (base64).
    • Errors: returns application_error if a signed URL download fails.
  • Dependencies

    • Bump to 6.2.0-canary.4.

@lucasfcosta lucasfcosta requested a review from a team as a code owner October 14, 2025 15:48
@pkg-pr-new
Copy link

pkg-pr-new bot commented Oct 14, 2025

Open in StackBlitz

npm i https://pkg.pr.new/resend/resend-node/resend@676

commit: 2934e81

@lucasfcosta lucasfcosta changed the title feat: SDK downloads from API's signed URLs instead of proxied routes feat: download from API's signed URLs instead of proxied routes Oct 14, 2025
Copy link
Contributor

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

Choose a reason for hiding this comment

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

No issues found across 5 files


const attachmentsWithContent = [];
for (const attachment of apiResponse.data.data) {
const downloadResponse = await fetch(attachment.download_url);
Copy link
Contributor

@emiliosheinz emiliosheinz Oct 14, 2025

Choose a reason for hiding this comment

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

Unlike this.resend.get, which wraps its internal fetch calls with a try/catch and normalizes network errors into the standard response format, this direct fetch invocation can throw under certain edge cases like DNS resolution failures, offline status, or other low-level network issues.

If unhandled, these exceptions would bypass the method’s usual error normalization flow, which may conflict with its original design of consistently returning an { data, error } structure.

I'm not sure if the omission of the try/catch blocks was intentional; if not, I would consider wrapping it with them to avoid unexpected errors being thrown.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great point!

@lucasfcosta lucasfcosta marked this pull request as draft October 14, 2025 17:35
@lucasfcosta lucasfcosta force-pushed the feature/product-796-api-yields-branded-signed-urls-instead-of-proxying-file branch from 7ed63ca to fe86a2a Compare October 14, 2025 20:13
@lucasfcosta lucasfcosta marked this pull request as ready for review October 14, 2025 20:13
Copy link
Contributor

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

Choose a reason for hiding this comment

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

No issues found across 5 files

@lucasfcosta lucasfcosta force-pushed the feature/product-796-api-yields-branded-signed-urls-instead-of-proxying-file branch from b3cfc07 to b39a39b Compare October 14, 2025 20:39
download_url,
...otherFields
} = attachment;
const downloadResult = await this.downloadAttachment(download_url);
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure if performance is a concern for this, but you might want to put this under a Promise.all or Promise.allSettled so that all the attachments are downloaded in parallel.

I missed that during my first review, sorry 😥

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, we discussed this internally as I was reviewing with @vieiralucas. For now we're going to download sequentially. The reason being that we want to review whether the SDK should download attachments at all. We're inclined to consider the download part as something that the user controls. That way they can download in whichever way they find best.

For now we decided to do it sequentially because it's a safe default. We're going to discuss this again today in one of our syncs.

@lucasfcosta lucasfcosta force-pushed the feature/product-796-api-yields-branded-signed-urls-instead-of-proxying-file branch from b39a39b to 6f5b97d Compare October 15, 2025 12:18
@lucasfcosta lucasfcosta force-pushed the feature/product-796-api-yields-branded-signed-urls-instead-of-proxying-file branch from 6f5b97d to 2934e81 Compare October 15, 2025 12:23
@lucasfcosta lucasfcosta merged commit b35f860 into canary Oct 15, 2025
11 checks passed
@lucasfcosta lucasfcosta deleted the feature/product-796-api-yields-branded-signed-urls-instead-of-proxying-file branch October 15, 2025 14:40
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.

4 participants