uSend Docs
Guides

CORS and browser requests

Why the usend API cannot be called from the browser, and what to do instead.

You may see an error like "blocked by CORS policy" when you call https://api.usend.et from JavaScript in a web page. This is by design.

Why it is blocked

The API only answers cross-origin browser requests for the usend dashboard. Your website's origin is not allowed, so the browser refuses to expose the response, and the preflight request fails.

Even if it were allowed, it would be a mistake: calling the API from a browser means putting your API key in the page. Anyone who opens the developer tools can copy it and send mail as you. See Handling API keys.

What to do instead

Send from a server you control and let the browser call that:

Text
browser  -->  your server / function  -->  usend API
          (no key)                  (API key in a secret)

Your server can be a route in your framework (Next.js, Remix, SvelteKit), a serverless function (Vercel, Cloudflare Workers, Lambda) or any backend.

A minimal proxy

TypeScript
// POST /api/contact from your own page
export async function POST(req: Request) {
  const { email, message } = await req.json();
  if (!email || !message || message.length > 5000) return new Response('Bad request', { status: 400 });

  const res = await fetch('https://api.usend.et/emails', {
    method: 'POST',
    headers: { Authorization: `Bearer ${process.env.USEND_API_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({
      from: 'Acme <[email protected]>',   // fixed, never taken from the request
      to: ['[email protected]'],        // fixed
      reply_to: email,
      subject: 'Contact form',
      text: message,
    }),
  });
  return new Response(null, { status: res.ok ? 204 : 502 });
}

Your own endpoint should:

  • Fix the from and to addresses yourself, so it cannot be used as an open mail relay.
  • Limit the size of the message and the rate per visitor (and add a CAPTCHA if the form is public).
  • Check the caller is allowed (a session, a signed token).

Server to server

Calls from a backend do not involve CORS at all: CORS is a browser rule. If you see a CORS error, your code is running in the browser.

Do not work around it

Do not try to disable CORS with a public proxy or a "no-cors" mode. A no-cors request cannot send the Authorization header or JSON body. A public CORS proxy would see your key.