# Send email from your app

> Your Cloud app sends email through Playcode, with no email provider to sign up for. Who receives it, what the send call answers, and what it costs.
> Source: https://playcode.io/docs/add-to-your-app/send-email - last reviewed 2026-10-10.
> Ask Playcode's agent: "Email me each time someone signs up." It writes the sending code, sends a test and reads the email back; verifying another inbox or your own domain stays with you.

Your Cloud app sends email through Playcode Email: password resets, receipts, notifications. There is no email provider to sign up for and no key to paste. Who receives the email depends on your plan and on the inboxes and domain you verified.

## Do it yourself

1. In the project, open **Settings** and choose **Email** under the project. The **Delivery** section shows what happens to the app's email: **Sending** (it reaches your team and your verified inboxes), **Sending · to anyone** (it reaches anyone, from your own domain), or **Capture** ("Every email is captured and stored - nothing reaches a real inbox").
2. Send from the app's backend. A new Cloud app already sends three emails: a welcome email when someone registers, a password reset link, and each contact form message to you. For another email, ask the agent, or call `@playcode/sdk`, which reads the app's `PLAYCODE_SECRET_KEY`:

   ```ts
   import { Playcode } from '@playcode/sdk'

   const pc = new Playcode()
   const { status } = await pc.email.send({
     to: 'anna@example.com',
     subject: 'Your receipt',
     html: '<p>Thank you for your order.</p>',
   })
   ```

3. Test it on yourself: leave out `to`, and the email goes to the project owner's account address, which needs no verification. The call answers `status: "sending"`. The agent can read the email back and follow its links.
4. To reach another inbox of yours, like a sales address, type it under **Notifications** and choose **Send verification**. Playcode emails it a link, and the address shows **Verified** once the link is opened.
5. To email your customers, verify your own domain. See [Send from your own domain](/docs/add-to-your-app/sending-domain).

> [!IMPORTANT]
> `PLAYCODE_SECRET_KEY` stays on the server. Never put it in browser code: anyone who has it can send email as your app.

### Who receives your app's email

| **Delivery** in **Settings**, **Email** | Who gets the email |
|---|---|
| **Capture** | Nobody. Playcode stores every email and delivers none; the agent can read them. The workspace has no Pro or Max plan |
| **Sending** | The project owner's account address, the sign-in addresses of the workspace's members, and the inboxes verified under **Notifications**. Email to anyone else is held |
| **Sending · to anyone** | Anyone, from your verified domain. An email to one person outside the workspace carries a one-click unsubscribe link |

### What the send call answers

| `status` | What happened |
|---|---|
| `sending` | Playcode accepted the email for delivery |
| `held` | Playcode keeps the email: a recipient is not verified, or the address is blocked after a bounce, a spam report or an unsubscribe. **Settings**, **Email** shows a **Deliver** button when the address can receive it |
| `captured` | Stored, not delivered: the workspace has no Pro or Max plan, or it is out of credits past the included amount |
| `withheld` | The app's sending is paused. This email is never sent |

Later, the agent sees whether the receiving server accepted the email (Delivered), refused it (Bounced), or the person marked it as spam (Complained).

> [!COST]
> Each billing cycle includes 500 recipients on Pro and 2,000 on Max. Past that, each recipient costs credits: **Settings**, **Email** shows the rate, "1 credit = 500 emails". An email to three people counts as three. Email to the workspace's members is free and does not count, and captured email costs nothing.

## If it doesn't work

### Settings shows Capture, or the email is held

Each case and its fix is on [An email did not arrive](/docs/help/email-did-not-arrive).

### "app-mail: this app is not registered with the email service - re-enable Email for the project"

The app has no email credential, which happens in projects created before Playcode Email. Ask the agent to switch on email for the app.

### "app-mail: no default inbox - the project has no owner address on file; push entitlements or pass `to`"

The email has no `to`, and Playcode has no owner address for the app yet. Pass `to`, or ask the agent to check the app's email setup.

### "app-mail: too many recipients (11 > 10)"

Send several emails instead. See [What your app may send](/docs/add-to-your-app/what-your-app-may-send) for the limits.

### "app-mail: either "html" or "text" body is required"

Add an `html` or a `text` body to the email.

### The call fails with 429: "burst quota exceeded" or "daily quota exceeded"

The app reached a sending limit. The `retry-after` header says how many seconds to wait. If the app sends the same email again and again, fix that first: a loop pauses sending.

### Replies do not reach you

Replies go to the email's `replyTo` address, or else to the address in its from line. In a new Cloud app, that from address is `noreply@example.com`, which nobody reads. Set `replyTo` on every email that expects an answer.

### The email arrived without its attachment

Playcode delivers email without attachments. Put the file behind a link in the email.

### Playcode has no record of the email

The app never sent it. Ask the agent: it lists the app's emails with their status and reason, and finds where the app's code stopped.

## Limits

- Playcode Email only sends. It hosts no inbox and cannot receive replies.
- Transactional email only: no newsletters or marketing. See [What your app may send](/docs/add-to-your-app/what-your-app-may-send).
- The number of recipients per email and of emails per minute and per day is limited. See [Sending limits](/docs/add-to-your-app/what-your-app-may-send#sending-limits).
- At zero credits, email past the included amount is stored, not delivered. Included email and email to the workspace's members still go out.
- A static site cannot send email: it has no server to keep the secret key.
