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

# Email API

> API endpoints to send transactional emails, manage Brevo templates, verify email addresses, and trigger welcome emails for new PropOps users.

The email API lets you send transactional emails, manage templates, and verify email addresses. All outbound email is delivered through the SMTP credentials configured in **Admin → Settings → Email**.

***

## Send an email

**`POST /api/email/send`**

Sends a transactional email using a named template and a set of merge variables.

**Required permission:** `api.email.send.manage`\
**Method:** POST only\
**Requires CSRF token.**

<ParamField body="to" type="string" required>
  Recipient email address.
</ParamField>

<ParamField body="template" type="string" required>
  Template name (see `GET /api/email/templates` for available templates).
</ParamField>

<ParamField body="variables" type="object">
  Key-value pairs to substitute into the template's merge fields.
</ParamField>

<ParamField body="job_id" type="integer">
  If provided, the email is logged against this job's record and threaded with any replies.
</ParamField>

<ParamField body="csrf_token" type="string" required>
  CSRF token from `GET /api/security/csrf-token`.
</ParamField>

```bash theme={null}
curl -X POST "https://propops.yourcompany.com/api/email/send" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "tenant@example.com",
    "template": "job_update",
    "variables": {
      "tenant_name": "Alice Smith",
      "job_ref": "JOB-1050",
      "status": "In Progress",
      "contractor_name": "Bob Plumbing Ltd"
    },
    "job_id": 1050,
    "csrf_token": "<csrf-token>"
  }'
```

```json theme={null}
{
  "success": true,
  "data": {
    "email_id": 9920,
    "status": "queued",
    "recipient": "tenant@example.com",
    "template": "job_update"
  },
  "message": "Email queued for delivery"
}
```

***

## List email templates

**`GET /api/email/templates`**

Returns all available email templates with their names, descriptions, and required merge variables.

**Required permission:** `api.email.send.manage`

```bash theme={null}
curl -X GET "https://propops.yourcompany.com/api/email/templates" \
  -H "Authorization: Bearer <token>"
```

```json theme={null}
{
  "success": true,
  "data": [
    {
      "name": "job_created",
      "display_name": "Job Created",
      "description": "Sent when a new job is raised. Notifies agents, contractors, and tenants.",
      "required_variables": ["recipient_name", "job_ref", "job_title", "property_address"]
    },
    {
      "name": "job_update",
      "display_name": "Job Update",
      "description": "Sent when a job status or key detail changes.",
      "required_variables": ["recipient_name", "job_ref", "status"]
    },
    {
      "name": "contractor_assigned",
      "display_name": "Contractor Assigned",
      "description": "Notifies the tenant and landlord when a contractor is assigned.",
      "required_variables": ["recipient_name", "job_ref", "contractor_name", "scheduled_date"]
    },
    {
      "name": "job_completed",
      "display_name": "Job Completed",
      "description": "Sent when a job is marked as completed.",
      "required_variables": ["recipient_name", "job_ref", "completion_date"]
    },
    {
      "name": "invoice_issued",
      "display_name": "Invoice Issued",
      "description": "Sent to the relevant party when an invoice is raised.",
      "required_variables": ["recipient_name", "invoice_number", "amount", "due_date"]
    },
    {
      "name": "welcome",
      "display_name": "Welcome Email",
      "description": "Sent to new users on account creation. The `temporary_password` variable is a system-generated one-time credential; users are required to change it on first login.",
      "required_variables": ["first_name", "login_url", "temporary_password"]
    },
    {
      "name": "password_reset",
      "display_name": "Password Reset",
      "description": "Sent when a user requests a password reset.",
      "required_variables": ["first_name", "reset_link", "expiry_minutes"]
    }
  ]
}
```

***

## Send a welcome email

**`POST /api/email/welcome`**

Sends the standard welcome email to a newly created user. This is called automatically when a user account is created but can be retriggered manually by a Staff user.

**Required permission:** `api.users.users.manage`\
**Requires CSRF token.**

<ParamField body="user_id" type="integer" required>
  ID of the user to send the welcome email to.
</ParamField>

<ParamField body="csrf_token" type="string" required>
  CSRF token.
</ParamField>

```bash theme={null}
curl -X POST "https://propops.yourcompany.com/api/email/welcome" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"user_id": 85, "csrf_token": "<csrf-token>"}'
```

```json theme={null}
{
  "success": true,
  "message": "Welcome email sent"
}
```

***

## Email verification

### Request an email verification code

**`POST /api/email/verify`**

Sends a one-time verification code to the authenticated user's email address. Codes expire after 15 minutes.

**Permission:** All authenticated users\
**Requires CSRF token.**

<ParamField body="action" type="string" required>
  Must be `send`.
</ParamField>

<ParamField body="csrf_token" type="string" required>
  CSRF token.
</ParamField>

```bash theme={null}
curl -X POST "https://propops.yourcompany.com/api/email/verify" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"action": "send", "csrf_token": "<csrf-token>"}'
```

```json theme={null}
{
  "success": true,
  "message": "Verification code sent to your email address"
}
```

***

### Verify the code

**`POST /api/email/verify`**

Submits the verification code sent to the user's email address.

**Permission:** All authenticated users\
**Requires CSRF token.**

<ParamField body="action" type="string" required>
  Must be `verify`.
</ParamField>

<ParamField body="code" type="string" required>
  The 6-digit verification code from the email.
</ParamField>

<ParamField body="csrf_token" type="string" required>
  CSRF token.
</ParamField>

```bash theme={null}
curl -X POST "https://propops.yourcompany.com/api/email/verify" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"action": "verify", "code": "482910", "csrf_token": "<csrf-token>"}'
```

```json theme={null}
{
  "success": true,
  "message": "Email address verified"
}
```

***

## Code examples

<CodeGroup>
  ```bash cURL theme={null}
  # Send a job update email
  curl -X POST "https://propops.yourcompany.com/api/email/send" \
    -H "Authorization: Bearer <token>" \
    -H "Content-Type: application/json" \
    -d '{
      "to": "landlord@example.com",
      "template": "job_completed",
      "variables": {
        "recipient_name": "Mr Davies",
        "job_ref": "JOB-1050",
        "completion_date": "14 June 2024"
      },
      "job_id": 1050,
      "csrf_token": "<csrf-token>"
    }'
  ```

  ```javascript JavaScript theme={null}
  const BASE = 'https://propops.yourcompany.com';
  const TOKEN = 'Bearer <token>';

  // Get CSRF token
  const csrfRes = await fetch(`${BASE}/api/security/csrf-token`, {
    headers: { Authorization: TOKEN },
  });
  const { data: { token: csrfToken } } = await csrfRes.json();

  // Send email
  const res = await fetch(`${BASE}/api/email/send`, {
    method: 'POST',
    headers: { Authorization: TOKEN, 'Content-Type': 'application/json' },
    body: JSON.stringify({
      to: 'landlord@example.com',
      template: 'job_completed',
      variables: {
        recipient_name: 'Mr Davies',
        job_ref: 'JOB-1050',
        completion_date: '14 June 2024',
      },
      job_id: 1050,
      csrf_token: csrfToken,
    }),
  });

  const result = await res.json();
  console.log(result.data.email_id);
  ```

  ```python Python theme={null}
  import requests

  BASE = 'https://propops.yourcompany.com'
  HEADERS = {'Authorization': 'Bearer <token>'}

  # Get CSRF token
  csrf = requests.get(f'{BASE}/api/security/csrf-token', headers=HEADERS).json()
  csrf_token = csrf['data']['token']

  # Send email
  res = requests.post(
      f'{BASE}/api/email/send',
      headers=HEADERS,
      json={
          'to': 'landlord@example.com',
          'template': 'job_completed',
          'variables': {
              'recipient_name': 'Mr Davies',
              'job_ref': 'JOB-1050',
              'completion_date': '14 June 2024',
          },
          'job_id': 1050,
          'csrf_token': csrf_token,
      },
  )
  print(res.json())
  ```
</CodeGroup>
