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

# Send Email

> Send a transactional email

## Description

Send a transactional email using Sendly. This is the most common and versatile endpoint.

## Parameters

<ParamField body="from" type="string" required>
  Email address of the sender. Must be a verified domain in your account.
  Examples: `noreply@yourdomain.com`, `no-reply@mail.yourdomain.com`
</ParamField>

<ParamField body="to" type="string | string[]" required>
  Email address(es) of the recipient. Can be a string or array.
</ParamField>

<ParamField body="subject" type="string" required>
  Email subject. Maximum 255 characters.
</ParamField>

<ParamField body="html" type="string">
  HTML content of the email. Required if `text` is not provided.
</ParamField>

<ParamField body="text" type="string">
  Plain text content. Used as fallback if `html` is not provided.
</ParamField>

<ParamField body="cc" type="string | string[]">
  CC recipient(s). Visible to all recipients.
</ParamField>

<ParamField body="bcc" type="string | string[]">
  BCC recipient(s). Visible only on server.
</ParamField>

<ParamField body="reply_to" type="string | string[]">
  Reply-to address(es).
</ParamField>

<ParamField body="headers" type="object">
  Custom headers. Example: `{"X-Custom-Header": "value"}`
</ParamField>

<ParamField body="attachments" type="array">
  Array of file attachments:

  * `filename` (string): File name
  * `content` (string | Buffer): Base64 encoded content
  * `content_type` (string): MIME type (e.g., `application/pdf`)
  * `cid` (string): Content ID for inline images
</ParamField>

<ParamField body="idempotencyKey" type="string">
  Unique key to prevent duplicates. Resending with the same key returns the previous response.
</ParamField>

<ParamField body="tracking" type="object">
  Tracking options:

  * `open` (boolean): Track opens. Default: false
  * `click` (boolean): Track clicks. Default: false
</ParamField>

## Response

<ResponseField name="id" type="string">
  Unique email ID. Use to check status later.
</ResponseField>

<ResponseField name="status" type="string" enum="['QUEUED', 'SENT', 'DELIVERED', 'BOUNCED', 'FAILED']">
  Current email status.
</ResponseField>

<ResponseField name="created_at" type="string">
  ISO 8601 timestamp of creation.
</ResponseField>

<ResponseField name="to" type="string">
  Recipient email address.
</ResponseField>

<ResponseField name="subject" type="string">
  Email subject.
</ResponseField>

<ResponseField name="from" type="string">
  Sender email address.
</ResponseField>

## Examples

### Basic Email

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.usesendly.app/v1/emails \
    -H "Authorization: Bearer se_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "from": "noreply@yourdomain.com",
      "to": "user@example.com",
      "subject": "Welcome!",
      "html": "<h1>Hello!</h1><p>Thanks for signing up.</p>"
    }'
  ```

  ```javascript SDK theme={null}
  import { Sendly } from '@sendlyapp/sdk'

  const client = new Sendly('se_your_api_key')

  const response = await client.emails.send({
    from: 'noreply@yourdomain.com',
    to: 'user@example.com',
    subject: 'Welcome!',
    html: '<h1>Hello!</h1><p>Thanks for signing up.</p>'
  })

  console.log('Email ID:', response.id)
  ```

  ```javascript SMTP theme={null}
  import nodemailer from 'nodemailer'

  const transporter = nodemailer.createTransport({
    host: 'smtp.usesendly.app',
    port: 587,
    secure: false,
    auth: {
      user: 'se_your_api_key',
      pass: 'se_your_api_key'
    }
  })

  await transporter.sendMail({
    from: 'noreply@yourdomain.com',
    to: 'user@example.com',
    subject: 'Welcome!',
    html: '<h1>Hello!</h1><p>Thanks for signing up.</p>'
  })
  ```
</CodeGroup>

### Multiple Recipients

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.usesendly.app/v1/emails \
    -H "Authorization: Bearer se_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "from": "noreply@yourdomain.com",
      "to": ["user1@example.com", "user2@example.com"],
      "cc": "admin@yourdomain.com",
      "subject": "Important Notice",
      "html": "<p>This is important...</p>"
    }'
  ```

  ```javascript SDK theme={null}
  await client.emails.send({
    from: 'noreply@yourdomain.com',
    to: ['user1@example.com', 'user2@example.com'],
    cc: 'admin@yourdomain.com',
    subject: 'Important Notice',
    html: '<p>This is important...</p>'
  })
  ```

  ```javascript SMTP theme={null}
  await transporter.sendMail({
    from: 'noreply@yourdomain.com',
    to: ['user1@example.com', 'user2@example.com'],
    cc: 'admin@yourdomain.com',
    subject: 'Important Notice',
    html: '<p>This is important...</p>'
  })
  ```
</CodeGroup>

### With Tracking

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.usesendly.app/v1/emails \
    -H "Authorization: Bearer se_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "from": "noreply@yourdomain.com",
      "to": "user@example.com",
      "subject": "Newsletter",
      "html": "<h1>Newsletter</h1><p>Content...</p>",
      "tracking": {
        "open": true,
        "click": true
      }
    }'
  ```

  ```javascript SDK theme={null}
  const response = await client.emails.send({
    from: 'noreply@yourdomain.com',
    to: 'user@example.com',
    subject: 'Newsletter',
    html: '<h1>Newsletter</h1><p>Content...</p>',
    tracking: {
      open: true,
      click: true
    }
  })
  ```

  ```javascript SMTP theme={null}
  await transporter.sendMail({
    from: 'noreply@yourdomain.com',
    to: 'user@example.com',
    subject: 'Newsletter',
    html: '<h1>Newsletter</h1><p>Content...</p>',
    headers: {
      'X-Track-Opens': 'true',
      'X-Track-Clicks': 'true'
    }
  })
  ```
</CodeGroup>

### With Attachments

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.usesendly.app/v1/emails \
    -H "Authorization: Bearer se_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "from": "noreply@yourdomain.com",
      "to": "user@example.com",
      "subject": "Your Document",
      "html": "<p>See attached PDF</p>",
      "attachments": [
        {
          "filename": "document.pdf",
          "content": "JVBERi0xLjQKJeLj...",
          "content_type": "application/pdf"
        }
      ]
    }'
  ```

  ```javascript SDK theme={null}
  import fs from 'fs'

  const pdfContent = fs.readFileSync('document.pdf')
  const base64 = pdfContent.toString('base64')

  await client.emails.send({
    from: 'noreply@yourdomain.com',
    to: 'user@example.com',
    subject: 'Your Document',
    html: '<p>See attached PDF</p>',
    attachments: [
      {
        filename: 'document.pdf',
        content: base64,
        content_type: 'application/pdf'
      }
    ]
  })
  ```

  ```javascript SMTP theme={null}
  import fs from 'fs'

  await transporter.sendMail({
    from: 'noreply@yourdomain.com',
    to: 'user@example.com',
    subject: 'Your Document',
    html: '<p>See attached PDF</p>',
    attachments: [
      {
        filename: 'document.pdf',
        path: 'document.pdf'
      }
    ]
  })
  ```
</CodeGroup>

### With Idempotency Key

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.usesendly.app/v1/emails \
    -H "Authorization: Bearer se_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "from": "noreply@yourdomain.com",
      "to": "user@example.com",
      "subject": "Payment Confirmation",
      "html": "<p>Your payment was processed</p>",
      "idempotencyKey": "payment-123"
    }'
  ```

  ```javascript SDK theme={null}
  await client.emails.send({
    from: 'noreply@yourdomain.com',
    to: 'user@example.com',
    subject: 'Payment Confirmation',
    html: '<p>Your payment was processed</p>',
    idempotencyKey: 'payment-123'
  })
  ```

  ```javascript SMTP theme={null}
  await transporter.sendMail({
    from: 'noreply@yourdomain.com',
    to: 'user@example.com',
    subject: 'Payment Confirmation',
    html: '<p>Your payment was processed</p>',
    messageId: 'payment-123'
  })
  ```
</CodeGroup>

## Error Handling

<CodeGroup>
  ```javascript SDK theme={null}
  import { SendlyError } from '@sendlyapp/sdk'

  try {
    await client.emails.send({
      from: 'noreply@invalid.com',
      to: 'user@example.com',
      subject: 'Email',
      html: '<p>Content</p>'
    })
  } catch (error) {
    if (error instanceof SendlyError) {
      console.error(`Error ${error.status}: ${error.message}`)
    }
  }
  ```

  ```bash cURL theme={null}
  # Will return 400 Bad Request with error details
  curl -X POST https://api.usesendly.app/v1/emails \
    -H "Authorization: Bearer se_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "from": "invalid-email",
      "to": "user@example.com"
    }'

  # Response:
  # {
  #   "code": "INVALID_EMAIL",
  #   "message": "The email address is invalid",
  #   "status": 400
  # }
  ```
</CodeGroup>

## Limits

* **Recipients per email**: Maximum 10,000
* **Attachment size**: Maximum 25 MB per email
* **Send rate**: 1,000 emails/minute
* **Auto-retries**: Up to 5 times for temporary errors

## Notes

* The `from` address must be a verified domain
* Emails are queued for immediate processing
* Initial status is always `QUEUED`
* Use `idempotencyKey` for critical transactions
* Open tracking requires an image in the email

***

Need help? Contact [support@usesendly.app](mailto:support@usesendly.app)
