> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sendpost.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Cloudflare Workers Quickstart

> Learn how to send emails with SendPost in Cloudflare Workers using the Fetch API

## Prerequisites

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

* [**Create a SendPost Account**](https://app.sendpost.io/register)
* [**Cloudflare Account**](https://dash.cloudflare.com/sign-up) (free tier works)
* [**Wrangler CLI**](https://developers.cloudflare.com/workers/wrangler/) installed
* A **Sub-Account API Key** from your SendPost dashboard

<Info>
  You can find your API keys in your [SendPost Dashboard](https://app.sendpost.io). Make sure to use your Sub-Account API Key for sending emails.
</Info>

## 1. Install Wrangler CLI

```bash theme={null}
npm install -g wrangler
```

## 2. Initialize Worker

```bash theme={null}
wrangler init sendpost-email
cd sendpost-email
```

## 3. Basic Email Worker

Update `src/index.ts`:

```typescript TypeScript theme={null}
export interface Env {
  SENDPOST_API_KEY: string;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    // Handle CORS
    if (request.method === 'OPTIONS') {
      return new Response(null, {
        headers: {
          'Access-Control-Allow-Origin': '*',
          'Access-Control-Allow-Methods': 'POST, OPTIONS',
          'Access-Control-Allow-Headers': 'Content-Type',
        },
      });
    }

    if (request.method !== 'POST') {
      return new Response(
        JSON.stringify({ error: 'Method not allowed' }),
        {
          status: 405,
          headers: {
            'Content-Type': 'application/json',
            'Access-Control-Allow-Origin': '*',
          },
        }
      );
    }

    try {
      const { to, subject, htmlBody, textBody } = await request.json();

      if (!to || !subject || !htmlBody) {
        return new Response(
          JSON.stringify({
            success: false,
            error: 'Missing required fields: to, subject, htmlBody',
          }),
          {
            status: 400,
            headers: {
              'Content-Type': 'application/json',
              'Access-Control-Allow-Origin': '*',
            },
          }
        );
      }

      // Prepare email message
      const emailMessage = {
        from: {
          email: 'hello@playwithsendpost.io',
          name: 'SendPost',
        },
        to: [{ email: to }],
        subject,
        htmlBody,
        textBody: textBody || htmlBody.replace(/<[^>]*>/g, ''),
        trackOpens: true,
        trackClicks: true,
      };

      // Send email via SendPost API
      const response = await fetch('https://api.sendpost.io/api/v1/subaccount/email/', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-SubAccount-ApiKey': env.SENDPOST_API_KEY,
        },
        body: JSON.stringify(emailMessage),
      });

      if (!response.ok) {
        const error = await response.text();
        throw new Error(`SendPost API error: ${error}`);
      }

      const result = await response.json();

      return new Response(
        JSON.stringify({
          success: true,
          messageId: result.messageId,
        }),
        {
          status: 200,
          headers: {
            'Content-Type': 'application/json',
            'Access-Control-Allow-Origin': '*',
          },
        }
      );
    } catch (error: any) {
      console.error('SendPost error:', error);
      return new Response(
        JSON.stringify({
          success: false,
          error: error.message,
        }),
        {
          status: 500,
          headers: {
            'Content-Type': 'application/json',
            'Access-Control-Allow-Origin': '*',
          },
        }
      );
    }
  },
};
```

## 4. Configure Worker

Update `wrangler.toml`:

```toml theme={null}
name = "sendpost-email"
main = "src/index.ts"
compatibility_date = "2023-10-30"

[vars]
# Environment variables (use secrets for sensitive data)
```

## 5. Set Secrets

Set the API key as a secret:

```bash theme={null}
wrangler secret put SENDPOST_API_KEY
```

Enter your Sub-Account API Key when prompted.

## 6. Deploy Worker

Deploy to Cloudflare:

```bash theme={null}
wrangler deploy
```

## 7. Common Use Cases

### Welcome Email Worker

Create `src/welcome-email.ts`:

```typescript TypeScript theme={null}
export interface Env {
  SENDPOST_API_KEY: string;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    if (request.method === 'OPTIONS') {
      return new Response(null, {
        headers: {
          'Access-Control-Allow-Origin': '*',
          'Access-Control-Allow-Methods': 'POST, OPTIONS',
          'Access-Control-Allow-Headers': 'Content-Type',
        },
      });
    }

    try {
      const { email, firstName } = await request.json();

      if (!email || !firstName) {
        return new Response(
          JSON.stringify({
            success: false,
            error: 'Missing required fields: email, firstName',
          }),
          {
            status: 400,
            headers: {
              'Content-Type': 'application/json',
              'Access-Control-Allow-Origin': '*',
            },
          }
        );
      }

      const emailMessage = {
        from: {
          email: 'hello@playwithsendpost.io',
          name: 'SendPost',
        },
        to: [
          {
            email,
            name: firstName,
            customFields: { firstName },
          },
        ],
        subject: 'Welcome {{firstName}}!',
        htmlBody: `
          <h1>Welcome, {{firstName}}!</h1>
          <p>Thank you for joining us. We're excited to have you on board.</p>
          <p>Get started by exploring our features:</p>
          <ul>
            <li>Feature 1</li>
            <li>Feature 2</li>
            <li>Feature 3</li>
          </ul>
          <p>If you have any questions, just reply to this email.</p>
          <p><a href="{{unsubscribe}}">Unsubscribe</a></p>
        `,
        textBody: `
          Welcome, {{firstName}}!
          
          Thank you for joining us. We're excited to have you on board.
          
          Get started by exploring our features:
          - Feature 1
          - Feature 2
          - Feature 3
          
          If you have any questions, just reply to this email.
          
          Unsubscribe: {{unsubscribe}}
        `,
        groups: ['welcome'],
        trackOpens: true,
        trackClicks: true,
      };

      const response = await fetch('https://api.sendpost.io/api/v1/subaccount/email/', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-SubAccount-ApiKey': env.SENDPOST_API_KEY,
        },
        body: JSON.stringify(emailMessage),
      });

      const result = await response.json();

      return new Response(
        JSON.stringify({
          success: true,
          messageId: result.messageId,
        }),
        {
          status: 200,
          headers: {
            'Content-Type': 'application/json',
            'Access-Control-Allow-Origin': '*',
          },
        }
      );
    } catch (error: any) {
      return new Response(
        JSON.stringify({
          success: false,
          error: error.message,
        }),
        {
          status: 500,
          headers: {
            'Content-Type': 'application/json',
            'Access-Control-Allow-Origin': '*',
          },
        }
      );
    }
  },
};
```

## 8. Testing Locally

Run locally:

```bash theme={null}
wrangler dev
```

Test your worker:

```bash theme={null}
curl -X POST http://localhost:8787 \
  -H "Content-Type: application/json" \
  -d '{
    "to": "user@example.com",
    "subject": "Test Email",
    "htmlBody": "<h1>Hello from Cloudflare Workers!</h1>"
  }'
```

## 9. Using with Pages Functions

If using Cloudflare Pages, create `functions/send-email.ts`:

```typescript TypeScript theme={null}
export async function onRequestPost(context: EventContext) {
  const { request, env } = context;
  // Same implementation as above
}
```

<Warning>
  Make sure your sender email domain is verified in your SendPost account before sending emails.
</Warning>

## 10. Next Steps

Explore more examples and use cases:

<Columns cols={3}>
  <Card title="Cloudflare Workers" icon="cloudflare" href="https://developers.cloudflare.com/workers/">
    Learn more about Cloudflare Workers
  </Card>

  <Card title="Wrangler CLI" icon="terminal" href="https://developers.cloudflare.com/workers/wrangler/">
    Learn more about Wrangler CLI
  </Card>

  <Card title="Quickstart Example" icon="github" href="https://github.com/sendpost/sendpost-cloudflare-workers-example">
    View a complete working example on GitHub
  </Card>
</Columns>
