How to Fix Resend Node SDK validation_error 403 Forbidden

Quick Diagnosis

  • ✓ Are you attempting to send an email to an external customer using the default onboarding@resend.dev sender?
  • ✓ Does your API request throw a 403 Forbidden response containing a validation_error exception token?
  • ✓ Did you specify a custom sender address in the from field whose domain is unverified in your Resend Dashboard?

Environment

The Resend SDK handles server-side mail routing across environments including Next.js Route Handlers, Express Server Contexts, Serverless Vercel Functions, and Custom Node API Endpoints.

Domain Configuration Sender Email Address Recipient Constraint API Execution Outcome
Unverified custom domain user@unverified.com Any email address validation_error 403 (Domain not verified)
Default Sandbox onboarding@resend.dev Owner email address Success (Testing mode)
Default Sandbox onboarding@resend.dev External customer email validation_error 403 (Sandbox restriction)
Verified custom domain contact@verified.com Any email address Success (Production mode)

Minimal Repro

When you send an email via Resend API, the service enforces strict domain validation criteria to protect email domains from spoofing and ensure delivery alignment under SPF, DKIM, and DMARC protocols. When using the default sandbox sender address (onboarding@resend.dev), Resend implements a restricted routing policy that allows messages to deliver only to the verified account owner’s email address. Attempting to send to any external address or using a custom domain that is not marked as verified in the Resend dashboard triggers a validation block. The API server intercepts this mismatch during the request authentication phase and aborts the request, returning a 403 Forbidden error with the validation_error exception token. To allow external sending, you must register the domain and update DNS public records.

import { Resend } from 'resend';

const resend = new Resend(process.env.RESEND_API_KEY);

export async function sendEmail() {
  // CRASH: Sending from onboarding@resend.dev to an external customer email
  const data = await resend.emails.send({
    from: 'onboarding@resend.dev',
    to: 'customer@externaldomain.com',
    subject: 'Hello Customer',
    html: '<p>Welcome to our service!</p>'
  });
  return data;
}
ResendError: validation_error (Status Code: 403)
"You can only send emails to your own email address while in sandbox mode. Verify your custom domain to send to other recipients."

Resolution

When resolving Resend validation errors, developers can choose between two main structural options depending on their deployment target.

Option A: Restrain Recipients for Sandbox Testing

If you are developing or testing, keeping your sender address configured as onboarding@resend.dev is applicable, provided you restrict the recipient list strictly to your registered account owner’s email address.

import { Resend } from 'resend';

const resend = new Resend(process.env.RESEND_API_KEY);

export async function sendSandboxEmail() {
  // Success: Sending to the verified account owner address
  const data = await resend.emails.send({
    from: 'onboarding@resend.dev',
    to: 'owner@registeredemail.com',
    subject: 'Sandbox Notification',
    html: '<p>Diagnostic trace completed.</p>'
  });
  return data;
}

Option B: Verify a Custom Domain for Production Sending

If you are preparing for production deployment, verifying a custom domain you own prevents sandbox sending restrictions and allows emailing external customers.

  1. Add your domain inside the Resend Domains dashboard to export the required SPF and DKIM public records.
  2. Register the specific TXT and MX records inside your registrar’s DNS settings panel.
  3. Once records propagate, update your application code to send from your custom domain.
import { Resend } from 'resend';

const resend = new Resend(process.env.RESEND_API_KEY);

export async function sendProductionEmail(recipient) {
  // Success: Sending to any recipient from a verified domain
  const data = await resend.emails.send({
    from: 'no-reply@verifieddomain.com',
    to: recipient,
    subject: 'Production Notification',
    html: '<p>Official notification content.</p>'
  });
  return data;
}

When This Fix Won’t Work

If you added your DNS records but local caches have not yet propagated, Resend dashboard verification check requests can fail. In this case, allow time for propagation or restart the verification checks within the Resend console.

Operational Runbook

Case 1: Testing & Development Environments

  1. Revert sender parameters in code to onboarding@resend.dev.
  2. Restrict recipient targets to the registered admin email address.

Case 2: Production Environments

  1. Register custom domains inside Resend domains setup.
  2. Bind the generated SPF and DKIM records to your registrar DNS configs.

Rollback Strategy

To roll back this change, restore the previous email sender configuration by replacing custom sender addresses in the from field with the default sandbox address (onboarding@resend.dev), constrain target recipients strictly to the registered account owner’s address, and remove custom domain verification assets from the application codebase.


Verification

  • Application mail dispatch requests complete returning HTTP 200 responses containing generated email message IDs.
  • Public DNS propagation query tools return active TXT records matching Resend SPF and DKIM public keys.
  • Resend administration dashboard displays verified status indicators for the target custom domain.

Error Trigger Point Lifecycle

Add domain in Resend console ➔ Configure DNS TXT records ➔ Wait for DNS propagation ➔ Initialize Resend client ➔ Call emails.send API [ERROR OCCURS HERE] ➔ Verify email delivery

References