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

# Send emails using the API

> Learn how to send emails using AhaSend's API v2 create-message endpoint with comprehensive examples and best practices

Send emails programmatically using AhaSend's powerful API v2 create-message endpoint. This guide covers everything from basic email sending to advanced features like template variables, bulk operations, and scheduled delivery.

<Info>
  **API v2 Features:** This guide covers the advanced API v2 create-message endpoint, which provides enhanced features like template substitutions, bulk sending, scheduled delivery, and comprehensive webhook support.
</Info>

## Quick Start

Here's a simple example to send your first email using the API:

```bash theme={null}
curl --request POST \
  --url https://api.ahasend.com/v2/accounts/{account_id}/messages \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "from": {
      "email": "hello@yourdomain.com",
      "name": "Your Company"
    },
    "recipients": [
      {
        "email": "user@example.com",
        "name": "John Doe"
      }
    ],
    "subject": "Welcome to our platform!",
    "text_content": "Thanks for signing up. We're excited to have you!"
  }'
```

## Authentication

All API requests require authentication using your API v2 key:

<AccordionGroup>
  <Accordion title="Authorization Header" icon="key">
    Include your API key in the Authorization header:

    ```
    Authorization: Bearer YOUR_API_KEY_HERE
    ```
  </Accordion>

  <Accordion title="Account ID" icon="id-card">
    Replace `{account_id}` in the URL with your actual account ID. The API Key must be created within this account.

    ```
    https://api.ahasend.com/v2/accounts/{account_id}/messages
    ```
  </Accordion>
</AccordionGroup>

<Info>
  **Need API Keys?** If you haven't created API v2 credentials yet, check out our [API Credentials guide](/send-api/credentials) for step-by-step instructions.
</Info>

## Basic Examples

<CodeGroup>
  ```json Plain Text Email theme={null}
  {
    "from": {
      "email": "hello@yourdomain.com",
      "name": "Your Company"
    },
    "recipients": [
      {
        "email": "user@example.com",
        "name": "John Doe"
      }
    ],
    "subject": "Welcome to our platform!",
    "text_content": "Thanks for signing up. We're excited to have you!"
  }
  ```

  ```json HTML Email theme={null}
  {
    "from": {
      "email": "hello@yourdomain.com",
      "name": "Your Company"
    },
    "recipients": [
      {
        "email": "user@example.com",
        "name": "John Doe"
      }
    ],
    "subject": "Welcome to our platform!",
    "html_content": "<html><body><h1>Welcome!</h1><p>Thanks for signing up. We're <strong>excited</strong> to have you!</p><p><a href='https://yourdomain.com/get-started'>Get Started</a></p></body></html>",
    "text_content": "Welcome! Thanks for signing up. We're excited to have you! Get started at https://yourdomain.com/get-started"
  }
  ```

  ```json With Template Variables theme={null}
  {
    "from": {
      "email": "hello@yourdomain.com",
      "name": "Your Company"
    },
    "recipients": [
      {
        "email": "user@example.com",
        "name": "John Doe"
      }
    ],
    "subject": "Welcome {{first_name}}!",
    "html_content": "<h1>Welcome {{first_name}}!</h1><p>Thanks for joining {{company}}. We're excited to have you!</p>",
    "text_content": "Welcome {{first_name}}! Thanks for joining {{company}}. We're excited to have you!",
    "substitutions": {
      "first_name": "John",
      "company": "Your Company"
    }
  }
  ```
</CodeGroup>

## Advanced Examples

<Note>
  **Multiple Recipients:** When you specify multiple recipients in the recipients array, AhaSend sends separate individual emails to each recipient. This is not one email with multiple addresses in the To/CC headers, but rather individual personalized emails where each recipient only sees their own email address and can receive personalized template substitutions.
</Note>

<CodeGroup>
  ```json Bulk Email Sending theme={null}
  {
    "from": {
      "email": "newsletter@yourdomain.com",
      "name": "Your Newsletter"
    },
    "recipients": [
      {
        "email": "user1@example.com",
        "name": "Alice Smith"
      },
      {
        "email": "user2@example.com",
        "name": "Bob Johnson"
      },
      {
        "email": "user3@example.com",
        "name": "Carol Wilson"
      }
    ],
    "subject": "Monthly Newsletter - {{month}}",
    "html_content": "<h1>{{month}} Newsletter</h1><p>Dear {{name}}, here's what's new this month...</p>",
    "text_content": "{{month}} Newsletter - Dear {{name}}, here's what's new this month...",
    "substitutions": {
      "month": "December",
      "name": "Valued Customer"
    }
  }
  ```

  ```json Scheduled Email theme={null}
  {
    "from": {
      "email": "reminders@yourdomain.com",
      "name": "Reminder Service"
    },
    "recipients": [
      {
        "email": "user@example.com",
        "name": "John Doe"
      }
    ],
    "subject": "Don't forget about your appointment tomorrow",
    "text_content": "Hi {{name}}, this is a friendly reminder about your appointment tomorrow at {{time}}.",
    "substitutions": {
      "name": "John",
      "time": "2:00 PM"
    },
    "schedule": {
      "first_attempt": "2024-12-24T18:00:00Z",
      "expires": "2024-12-25T18:00:00Z"
    }
  }
  ```

  ```json Transactional Email with Retention theme={null}
  {
    "from": {
      "email": "orders@yourdomain.com",
      "name": "Your Store"
    },
    "recipients": [
      {
        "email": "customer@example.com",
        "name": "Jane Customer"
      }
    ],
    "subject": "Order #{{order_id}} Confirmation",
    "html_content": "<h1>Order Confirmation</h1><p>Thank you {{name}}! Your order #{{order_id}} for ${{total}} has been confirmed.</p><p>Tracking: {{tracking}}</p>",
    "text_content": "Thank you {{name}}! Your order #{{order_id}} for ${{total}} has been confirmed. Tracking: {{tracking}}",
    "substitutions": {
      "name": "Jane",
      "order_id": "12345",
      "total": "99.99",
      "tracking": "TRK123456789"
    },
    "retention": {
      "metadata": 30,
      "data": 7
    }
  }
  ```

  ```json Testing with Sandbox Mode theme={null}
  {
    "from": {
      "email": "hello@yourdomain.com",
      "name": "Your Company"
    },
    "recipients": [
      {
        "email": "test@example.com",
        "name": "Test User"
      }
    ],
    "subject": "Test Email",
    "text_content": "This is a test email sent in sandbox mode.",
    "sandbox": true,
    "sandbox_result": "deliver"
  }
  ```
</CodeGroup>

## Response Handling

The API returns a response with information about each message created:

### Successful Response (200)

```json theme={null}
{
  "object": "list",
  "data": [
    {
      "object": "message",
      "id": "3f8e2b1a-7c4d-4e2a-9b1e-2f3a4b5c6d7e",
      "recipient": {
        "email": "user@example.com",
        "name": "John Doe",
        "substitution_data": {
          "first_name": "John",
          "company": "Your Company"
        }
      },
      "status": "queued",
      "error": null,
      "schedule": {
        "first_attempt": "2024-01-15T10:30:00Z",
        "expires": "2024-01-16T10:30:00Z"
      }
    }
  ]
}
```

### Response Fields

<AccordionGroup>
  <Accordion title="Message Status" icon="info">
    * **`queued`** - Message accepted and queued for delivery
    * **`scheduled`** - Message scheduled for future delivery
    * **`failed`** - Message failed validation or processing
  </Accordion>

  <Accordion title="Message ID" icon="fingerprint">
    Unique identifier for tracking the message through webhooks and logs
  </Accordion>

  <Accordion title="Schedule Information" icon="calendar">
    If you include the `schedule` parameter in your request, the response will include timing information including the scheduled first attempt and expiration.
  </Accordion>
</AccordionGroup>

## Error Handling

Handle different HTTP status codes appropriately:

<AccordionGroup>
  <Accordion title="400 - Bad Request" icon="xmark">
    **Common causes:**

    * Missing required fields (`from`, `recipients`, `subject`)
    * Invalid email addresses
    * Missing `text_content` or `html_content`
    * Invalid retention values (outside 1-30 days range)

    **Example error response:**

    ```json theme={null}
    {
      "error": {
        "type": "validation_error",
        "message": "Either text_content or html_content is required"
      }
    }
    ```
  </Accordion>

  <Accordion title="401 - Unauthorized" icon="lock">
    **Common causes:**

    * Missing or invalid API key
    * Malformed Authorization header

    **Solution:**

    ```bash theme={null}
    --header 'Authorization: Bearer YOUR_VALID_API_KEY'
    ```
  </Accordion>

  <Accordion title="403 - Forbidden" icon="shield-xmark">
    **Common causes:**

    * Sender domain not verified
    * API key doesn't have permission for the account
    * Account suspended or over limits

    **Solution:** Verify domain in dashboard and check account status
  </Accordion>

  <Accordion title="409 - Conflict" icon="triangle-exclamation">
    **Idempotency key conflict**

    * Request with same idempotency key already processed
    * Returns original response for duplicate requests
  </Accordion>
</AccordionGroup>

## Validation Requirements

Based on the [API documentation](https://ahasend.com/docs/api-reference/messages/create-message), ensure your requests meet these requirements:

<AccordionGroup>
  <Accordion title="Content Requirements" icon="file-lines">
    * Either `text_content` or `html_content` is required
    * Both can be provided for multipart emails
    * Use proper HTML structure for `html_content`
  </Accordion>

  <Accordion title="Sender Domain" icon="globe">
    * `from.email` must be from a domain you own
    * Domain must have valid DNS records configured
    * Domain must be verified in your AhaSend account
  </Accordion>

  <Accordion title="Retention Settings" icon="clock">
    * `retention.metadata` must be between 1 and 30 days
    * `retention.data` must be between 0 and 30 days
    * Use 0 for immediate content deletion after processing
  </Accordion>

  <Accordion title="Scheduling Format" icon="calendar">
    * Schedule times must be in RFC3339 format
    * Example: `"2024-12-25T10:30:00Z"`
    * Times should be in UTC timezone
  </Accordion>
</AccordionGroup>

## Best Practices

<AccordionGroup>
  <Accordion title="Idempotency" icon="repeat">
    Use [idempotency keys](/api-reference/idempotency) for safe retries:

    ```bash theme={null}
    --header 'Idempotency-Key: unique-request-id-12345'
    ```

    Keys expire after 24 hours and ensure duplicate requests return the same response.
  </Accordion>

  <Accordion title="Template Variables" icon="code">
    AhaSend supports [MiniJinja](https://github.com/mitsuhiko/minijinja) templating language for email content.

    * Use descriptive variable names
    * Provide fallback values in templates
    * Validate variables before sending
    * Escape HTML content in variables
  </Accordion>

  <Accordion title="Bulk Operations" icon="layer-group">
    **Efficient bulk sending:**

    * Send up to 100 requests per second
    * Send up to 100 recipients per request
    * Handle partial failures gracefully
    * Implement retry logic for failed messages
  </Accordion>

  <Accordion title="Error Handling" icon="shield-check">
    **Robust error handling:**

    * Implement exponential backoff for retries
    * Log API responses for debugging
    * Handle different status codes appropriately
    * Use [webhooks](/webhooks) for delivery confirmation
  </Accordion>
</AccordionGroup>
