# Send email from Express

> Send email from a Node.js Express app with Vaartix, and receive signed webhooks.

Source: https://vaartix.com/docs/guides/express/

1.  **Install the SDK**

    ```sh
    npm install vaartix
    ```

    Keep your key in an environment variable, for example in `.env` loaded with `node --env-file=.env server.js`:

    .env

    ```sh
    VAARTIX_API_KEY=vx_live_...
    ```

2.  **Send an email from a route**

    server.js

    ```js
    import express from 'express';
    import { Vaartix } from 'vaartix';

    const app = express();
    const vaartix = new Vaartix(); // reads VAARTIX_API_KEY

    app.post('/orders/:id/confirm', express.json(), async (req, res) => {
      const { data, error } = await vaartix.emails.send(
        {
          from: 'Acme <orders@acme.in>',
          to: req.body.email,
          subject: `Order ${req.params.id} is confirmed`,
          html: `<p>Thanks! We'll ship order <strong>${req.params.id}</strong> soon.</p>`,
        },
        // Retrying the request won't send the email twice.
        { idempotencyKey: `order-confirmed-${req.params.id}` },
      );
      if (error) return res.status(error.statusCode ?? 500).json({ error: error.message });
      res.json({ emailId: data.id });
    });

    app.listen(3000);
    ```

    The SDK never throws for API or network errors: check `error`. Its `type` tells you what went wrong (see [Errors](https://vaartix.com/docs/concepts/errors/)).

Until your domain is verified, send from `@test.vaartix.com` to `delivered@test.vaartix.com`: see [Test mode](https://vaartix.com/docs/sending/test-mode/).

## Receiving webhooks

Signatures are checked against the exact bytes Vaartix sent, so use `express.raw()` on the webhook route instead of `express.json()`:

server.js

```js
import { verifyWebhook, WebhookVerificationError } from 'vaartix';

app.post('/webhooks/vaartix', express.raw({ type: 'application/json' }), (req, res) => {
  let event;
  try {
    event = verifyWebhook({
      payload: req.body, // a Buffer
      headers: req.headers,
      secret: process.env.VAARTIX_WEBHOOK_SECRET,
    });
  } catch (err) {
    if (err instanceof WebhookVerificationError) return res.sendStatus(400);
    throw err;
  }

  switch (event.type) {
    case 'email.bounced':
    case 'email.complained':
      // Stop emailing event.data.recipient
      break;
    case 'email.delivered':
      // Mark it delivered in your database
      break;
  }
  res.sendStatus(200);
});
```

If `app.use(express.json())` is registered for the whole app, register the webhook route before it, or the body arrives already parsed and the signature check fails.
