Skip to main content
Encore is an open-source TypeScript framework that provisions infrastructure directly from your application code, with built-in observability and cloud deployment.

Use this pre-built prompt to get started faster.

CursorOpen in Cursor

Prerequisites

To get the most out of this guide, you’ll need to:

1. Create an Encore app

The quickest way to get started is with the Resend starter template:
encore app create --example=ts/resend
Or install the SDK into an existing Encore project:
npm install resend

2. Set your API key

Encore has built-in secrets management. Store your Resend API key as a secret - no .env files needed:
encore secret set --type dev,local,pr,production ResendAPIKey
Initialize the client using the secret:
email/resend.ts
import { Resend } from 'resend';
import { secret } from 'encore.dev/config';

const resendApiKey = secret('ResendAPIKey');

export const resend = new Resend(resendApiKey());

3. Define a service

Every Encore.ts service needs a service definition file:
email/encore.service.ts
import { Service } from 'encore.dev/service';

export default new Service('email');

4. Send email using an API endpoint

Create a type-safe API endpoint to send emails:
email/send.ts
import { api } from 'encore.dev/api';
import { resend } from './resend';

interface SendRequest {
  to: string;
  subject: string;
  html: string;
}

interface SendResponse {
  id: string;
}

export const sendEmail = api(
  { expose: true, method: 'POST', path: '/email/send' },
  async (req: SendRequest): Promise<SendResponse> => {
    const { data, error } = await resend.emails.send({
      from: 'Acme <onboarding@resend.dev>',
      to: req.to,
      subject: req.subject,
      html: req.html,
    });

    if (error) {
      throw new Error(`Failed to send email: ${error.message}`);
    }

    return { id: data!.id };
  },
);

5. Async delivery with Pub/Sub (optional)

For production, use Encore’s built-in Pub/Sub to send emails asynchronously with automatic retries:
email/topic.ts
import { Topic, Subscription } from 'encore.dev/pubsub';
import { resend } from './resend';

interface EmailEvent {
  to: string;
  subject: string;
  html: string;
}

export const emailTopic = new Topic<EmailEvent>('emails', {
  deliveryGuarantee: 'at-least-once',
});

const _ = new Subscription(emailTopic, 'send-email', {
  handler: async (event) => {
    const { data, error } = await resend.emails.send({
      from: 'Acme <onboarding@resend.dev>',
      to: event.to,
      subject: event.subject,
      html: event.html,
    });

    if (error) {
      throw new Error(error.message);
    }

    console.log('Email sent:', data?.id);
  },
});
Then publish from any endpoint:
import { emailTopic } from './topic';

await emailTopic.publish({
  to: 'delivered@resend.dev',
  subject: 'Welcome!',
  html: '<p>Thanks for signing up.</p>',
});

6. Run the app

encore run
Your API is running at http://localhost:4000. Send a test email:
curl -X POST http://localhost:4000/email/send \
  -H "Content-Type: application/json" \
  -d '{"to":"delivered@resend.dev","subject":"Hello World","html":"<strong>It works!</strong>"}'

7. AI skills for Encore.ts

If you’re using an AI coding assistant, install the Encore skills for context-aware help with APIs, services, Pub/Sub, databases, auth, and more:
npx skills add encoredev/skills

8. Try it yourself

Resend Starter

Full example with Pub/Sub email delivery

Encore.ts Docs

Encore.ts documentation