Email API Integration Guide

Overview

This guide explains how to integrate with the Email API using API keys. The API provides endpoints for sending individual and bulk email messages, checking message status, and managing email configuration.


Table of Contents

  1. Getting Started
  2. Authentication
  3. Endpoints
  4. Request/Response Formats
  5. Error Handling
  6. Rate Limits & Quotas
  7. Code Examples
  8. Webhooks
  9. Best Practices

Getting Started

Prerequisites

  1. Active Company Account: You need a company account registered in the system
  2. API Key: Generate an API key from the Admin Dashboard (Admin > API Keys)
  3. Active Subscription: Your company must have an active subscription with Email quota
  4. SMTP Configuration: Your company must have configured SMTP settings (or use default system SMTP)

Base URL

Production: https://prosendi.com/api
Development: http://localhost:8000/api

Authentication

API Key Authentication

All API requests require authentication using an API key. The API key must be:

  1. Active - Not deactivated by an administrator
  2. Not Expired - Must have a valid expiration date
  3. Valid - Properly associated with your company account
  4. Service-Specific - Matches the service type you're accessing (email, sms, whatsapp)

API Key Validation

The system automatically validates your API key on every request:

  • Existence Check: API key exists in the system
  • Active Status: active field is true
  • Expiration Check: Current date is before expires_date
  • Company Status: Associated company account is active

If any validation fails, the request is rejected with a 401 Unauthorized response.

Include your API key in one of the following ways:

Option 1: Custom Header (Recommended)

X-API-Key: your_api_key_here

Option 2: Authorization Header

Authorization: Bearer your_api_key_here

Example

curl -X POST https://prosendi.com/api/email/send \
  -H "X-API-Key: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"recipient": "[email protected]", "subject": "Hello", "message": "<h1>Hello World</h1>"}'

Endpoints

1. Send Email

Send a single email message to a recipient.

Endpoint: POST /api/email/send

Authentication: Required (API Key + Quota Check)

Request Body:

{
    "recipient": "[email protected]",
    "subject": "Your email subject",
    "message": "<html><body><h1>Your HTML email content</h1></body></html>",
    "from_email": "[email protected]",
    "from_name": "John Doe",
    "reply_to": "[email protected]",
    "cc": ["[email protected]", "[email protected]"],
    "bcc": ["[email protected]"],
    "campaign_id": 5
}

Success Response (200):

{
    "success": true,
    "message": "Email envoyé avec succès",
    "data": {
        "email_id": "uuid-here",
        "recipient": "[email protected]",
        "subject": "Your email subject",
        "from": "[email protected]",
        "status": "sent",
        "sent_at": "2025-11-04T10:30:00.000000Z"
    }
}

Error Responses:

Status Code Error Type Description
400 Bad Request Invalid email format or missing required fields
401 Unauthorized Missing or invalid API key
403 Forbidden Company account is inactive
429 Too Many Requests Quota exceeded
500 Internal Error Server error or SMTP configuration issue

2. Send Bulk Email

Send multiple email messages in a single request.

Endpoint: POST /api/email/send-bulk

Authentication: Required (API Key + Quota Check)

Request Body:

{
    "emails": [
        {
            "recipient": "[email protected]",
            "subject": "Personalized Subject 1",
            "message": "<html><body><h1>Hello User 1</h1></body></html>"
        },
        {
            "recipient": "[email protected]",
            "subject": "Personalized Subject 2",
            "message": "<html><body><h1>Hello User 2</h1></body></html>"
        }
    ],
    "from_email": "[email protected]",
    "from_name": "Company Name",
    "reply_to": "[email protected]",
    "campaign_id": 5
}

Constraints:

  • Maximum 100 emails per request
  • All recipients must be valid email addresses
  • HTML content is supported
  • Plain text fallback can be provided

Success Response (200):

{
    "success": true,
    "message": "Envoi terminé: 2 succès, 0 échecs",
    "summary": {
        "total": 2,
        "success": 2,
        "failed": 0
    },
    "results": [
        {
            "recipient": "[email protected]",
            "success": true,
            "email_id": "uuid-1",
            "status": "sent"
        },
        {
            "recipient": "[email protected]",
            "success": true,
            "email_id": "uuid-2",
            "status": "sent"
        }
    ]
}

3. Check Email Status

Retrieve the status of a previously sent email.

Endpoint: GET /api/email/status/{email_id}

Authentication: Required (API Key only)

Parameters:

  • email_id (path parameter): UUID of the email message

Success Response (200):

{
    "success": true,
    "data": {
        "email_id": "uuid-here",
        "recipient": "[email protected]",
        "subject": "Your email subject",
        "sender": "[email protected]",
        "message": "<html>...</html>",
        "status": "sent",
        "status_label": "Sent",
        "sent_at": "2025-11-04T10:30:00.000000Z",
        "delivered_at": "2025-11-04T10:30:05.000000Z",
        "opened_at": "2025-11-04T10:35:00.000000Z",
        "clicked_at": null,
        "failed_at": null,
        "failure_reason": null,
        "bounce_reason": null,
        "opens_count": 1,
        "clicks_count": 0,
        "campaign_id": 5
    }
}

Status Values:

Status Description
pending Email queued for sending
sent Email sent successfully
delivered Email delivered to recipient
opened Email opened by recipient
clicked Link in email clicked
bounced Email bounced (delivery failed)
failed Email failed to send
cancelled Email was cancelled

4. Get Email Configuration

Retrieve your company's email configuration and SMTP settings.

Endpoint: GET /api/email/configuration

Authentication: Required (API Key only)

Success Response (200):

{
    "success": true,
    "data": {
        "provider": "smtp",
        "sender_name": "Your Company Name",
        "sender_address": "[email protected]",
        "smtp_configured": true,
        "default_from_address": "[email protected]",
        "default_from_name": "1Simple1",
        "reply_to": "[email protected]"
    }
}

5. Test Email Connection

Test the email SMTP connection configuration.

Endpoint: GET /api/email/test-connection

Authentication: Required (API Key only)

Query Parameters:

  • test_email (optional): Email address to send test email to (defaults to company email)

Success Response (200):

{
    "success": true,
    "message": "Test email envoyé avec succès",
    "data": {
        "test_email": "[email protected]",
        "connection_status": "success",
        "provider": "smtp"
    }
}

Request/Response Formats

Email Address Format

Email addresses must follow the standard email format:

^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$

Valid Examples:

Invalid Examples:

  • invalid-email (missing @ and domain)
  • @example.com (missing local part)
  • user@ (missing domain)

Message Format

  • Content Type: HTML is supported (default)
  • Encoding: UTF-8
  • Maximum Size: 10MB per email
  • Supported HTML: Full HTML support with inline CSS

Subject Format

  • Character Limit: 255 characters (recommended: 50-70 for best display)
  • Encoding: UTF-8
  • Supported Characters: All standard text characters and emojis

JSON Headers

Always include:

Content-Type: application/json
Accept: application/json

Error Handling

Standard Error Response

{
    "success": false,
    "message": "Human-readable error message",
    "error": "error_code",
    "data": {}
}

Common Error Codes

Error Code HTTP Status Description
missing_api_key 401 API key not provided
invalid_api_key 401 API key is invalid
inactive_api_key 401 API key is expired or deactivated
inactive_company 403 Company account is inactive
service_type_mismatch 403 API key is not valid for this service type
quota_exceeded 429 Email quota exceeded
invalid_request 400 Request validation failed
invalid_email 400 Invalid email address format
smtp_error 500 SMTP configuration or connection error
company_not_found 500 Company not found for this API key

Quota Exceeded Response

{
    "success": false,
    "message": "Quota exceeded",
    "error": "quota_exceeded",
    "data": {
        "service_type": "email",
        "requested": 10,
        "remaining": 0,
        "total_quota": 10000,
        "usage_percentage": 100.0
    }
}

SMTP Error Response

{
    "success": false,
    "message": "Failed to authenticate on SMTP server",
    "error": "smtp_error",
    "data": {
        "provider": "smtp",
        "host": "smtp.example.com",
        "error_details": "Authentication unsuccessful, basic authentication is disabled."
    }
}

Rate Limits & Quotas

Quota Management

  • Quota Checking: Automatic for all send operations
  • Per-Request Check: System verifies available quota before processing
  • Bulk Requests: Total emails count against quota

Quota Information

Check your quota status:

  1. Dashboard: Admin Dashboard > Email Quota
  2. API Response: Included in quota exceeded errors

Example Quota Breakdown

Total Quota: 10,000 emails/month
Sent This Month: 7,500
Remaining: 2,500
Usage: 75%

Rate Limiting

  • Bulk Requests: Limit to 100 emails per request
  • Throttling: 100ms delay between emails in bulk operations
  • Daily Limits: Configurable per company

Code Examples

JavaScript/Node.js

const axios = require("axios");

const API_KEY = "your_api_key_here";
const BASE_URL = "https://prosendi.com/api";

// Send Single Email
async function sendEmail(recipient, subject, message, options = {}) {
    try {
        const response = await axios.post(
            `${BASE_URL}/email/send`,
            {
                recipient,
                subject,
                message,
                ...options
            },
            {
                headers: {
                    "X-API-Key": API_KEY,
                    "Content-Type": "application/json",
                },
            }
        );

        console.log("Email sent:", response.data);
        return response.data;
    } catch (error) {
        console.error("Error:", error.response?.data || error.message);
        throw error;
    }
}

// Send Bulk Email
async function sendBulkEmail(emails, options = {}) {
    try {
        const response = await axios.post(
            `${BASE_URL}/email/send-bulk`,
            { emails, ...options },
            {
                headers: {
                    "X-API-Key": API_KEY,
                    "Content-Type": "application/json",
                },
            }
        );

        console.log("Bulk email sent:", response.data);
        return response.data;
    } catch (error) {
        console.error("Error:", error.response?.data || error.message);
        throw error;
    }
}

// Check Email Status
async function checkEmailStatus(emailId) {
    try {
        const response = await axios.get(
            `${BASE_URL}/email/status/${emailId}`,
            {
                headers: { "X-API-Key": API_KEY },
            }
        );

        console.log("Email status:", response.data);
        return response.data;
    } catch (error) {
        console.error("Error:", error.response?.data || error.message);
        throw error;
    }
}

// Usage
sendEmail(
    "[email protected]",
    "Welcome!",
    "<html><body><h1>Welcome to our service!</h1></body></html>",
    {
        from_name: "My Company",
        reply_to: "[email protected]"
    }
);

Python

import requests

API_KEY = 'your_api_key_here'
BASE_URL = 'https://prosendi.com/api'

def send_email(recipient, subject, message, **options):
    """Send a single email"""
    url = f'{BASE_URL}/email/send'
    headers = {
        'X-API-Key': API_KEY,
        'Content-Type': 'application/json'
    }
    data = {
        'recipient': recipient,
        'subject': subject,
        'message': message,
        **options
    }

    response = requests.post(url, json=data, headers=headers)
    return response.json()

def send_bulk_email(emails, **options):
    """Send bulk emails"""
    url = f'{BASE_URL}/email/send-bulk'
    headers = {
        'X-API-Key': API_KEY,
        'Content-Type': 'application/json'
    }
    data = {
        'emails': emails,
        **options
    }

    response = requests.post(url, json=data, headers=headers)
    return response.json()

def check_email_status(email_id):
    """Check email status"""
    url = f'{BASE_URL}/email/status/{email_id}'
    headers = {'X-API-Key': API_KEY}

    response = requests.get(url, headers=headers)
    return response.json()

# Usage
result = send_email(
    '[email protected]',
    'Welcome!',
    '<html><body><h1>Welcome!</h1></body></html>',
    from_name='My Company'
)
print(result)

PHP

<?php

$apiKey = 'your_api_key_here';
$baseUrl = 'https://prosendi.com/api';

// Send Single Email
function sendEmail($recipient, $subject, $message, $options = []) {
    global $apiKey, $baseUrl;

    $ch = curl_init($baseUrl . '/email/send');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'X-API-Key: ' . $apiKey,
        'Content-Type: application/json'
    ]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(array_merge([
        'recipient' => $recipient,
        'subject' => $subject,
        'message' => $message
    ], $options)));

    $response = curl_exec($ch);
    curl_close($ch);

    return json_decode($response, true);
}

// Send Bulk Email
function sendBulkEmail($emails, $options = []) {
    global $apiKey, $baseUrl;

    $ch = curl_init($baseUrl . '/email/send-bulk');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'X-API-Key: ' . $apiKey,
        'Content-Type: application/json'
    ]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(array_merge([
        'emails' => $emails
    ], $options)));

    $response = curl_exec($ch);
    curl_close($ch);

    return json_decode($response, true);
}

// Check Email Status
function checkEmailStatus($emailId) {
    global $apiKey, $baseUrl;

    $ch = curl_init($baseUrl . '/email/status/' . $emailId);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'X-API-Key: ' . $apiKey
    ]);

    $response = curl_exec($ch);
    curl_close($ch);

    return json_decode($response, true);
}

// Usage
$result = sendEmail(
    '[email protected]',
    'Welcome!',
    '<html><body><h1>Welcome!</h1></body></html>',
    ['from_name' => 'My Company']
);
print_r($result);
?>

cURL

#!/bin/bash

API_KEY="your_api_key_here"
BASE_URL="https://prosendi.com/api"

# Send Single Email
send_email() {
    curl -X POST "$BASE_URL/email/send" \
      -H "X-API-Key: $API_KEY" \
      -H "Content-Type: application/json" \
      -d "{
        \"recipient\": \"\",
        \"subject\": \"\",
        \"message\": \"\"
      }"
}

# Send Bulk Email
send_bulk_email() {
    curl -X POST "$BASE_URL/email/send-bulk" \
      -H "X-API-Key: $API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "emails": [
          {"recipient": "[email protected]", "subject": "Hello 1", "message": "<h1>Hello</h1>"},
          {"recipient": "[email protected]", "subject": "Hello 2", "message": "<h1>Hello</h1>"}
        ]
      }'
}

# Check Email Status
check_status() {
    curl -X GET "$BASE_URL/email/status/" \
      -H "X-API-Key: $API_KEY"
}

# Usage
send_email "[email protected]" "Hello" "<html><body><h1>Hello from bash!</h1></body></html>"

Webhooks

Note: Webhooks are not yet implemented but planned for future releases.

Planned webhook events:

  • email.sent - Email sent successfully
  • email.delivered - Email delivered to recipient
  • email.opened - Email opened by recipient
  • email.clicked - Link in email clicked
  • email.bounced - Email bounced (delivery failed)
  • email.failed - Email failed to send

Best Practices

1. API Key Security

  • Never commit API keys to version control
  • Store keys securely in environment variables
  • Rotate keys regularly
  • Revoke keys immediately if compromised

2. Error Handling

Always implement robust error handling:

try {
    const result = await sendEmail(recipient, subject, message);

    if (!result.success) {
        if (result.error === "quota_exceeded") {
            // Handle quota exceeded
            console.log("Remaining quota:", result.data.remaining);
        } else if (result.error === "smtp_error") {
            // Handle SMTP errors
            console.error("SMTP error:", result.data.error_details);
        } else {
            // Handle other errors
            console.error("Error:", result.message);
        }
    }
} catch (error) {
    // Handle network or unexpected errors
    console.error("Request failed:", error.message);
}

3. Rate Limiting

  • Bulk Requests: Limit to 100 emails per request
  • Throttling: Add delays between bulk requests
  • Retry Logic: Implement exponential backoff for failed requests

4. Email Address Validation

Always validate email addresses before sending:

function isValidEmail(email) {
    const pattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
    return pattern.test(email);
}

if (!isValidEmail(recipient)) {
    throw new Error("Invalid email address format");
}

5. Email Content Best Practices

  • HTML Structure: Use proper HTML structure with <html>, <head>, and <body> tags
  • Inline CSS: Use inline CSS for better email client compatibility
  • Alt Text: Always include alt text for images
  • Plain Text Fallback: Consider providing plain text version
  • Mobile Responsive: Design emails to be mobile-friendly
  • Unsubscribe Link: Always include unsubscribe link for marketing emails

6. Personalization

Use variables to personalize emails:

const personalizedMessage = `
    <html>
        <body>
            <h1>Hello ${firstName}!</h1>
            <p>Thank you for joining us, ${fullName}.</p>
        </body>
    </html>
`;

7. Monitoring

  • Track sent/failed email counts
  • Monitor quota usage regularly
  • Set up alerts for low quota
  • Track open and click rates
  • Monitor bounce rates
  • Log all API requests for debugging

8. SMTP Configuration

  • Office 365/Outlook: Use app passwords instead of regular passwords when 2FA is enabled
  • Gmail: Use app-specific passwords for SMTP
  • Custom SMTP: Ensure proper port and encryption settings (TLS/SSL)
  • Test Connection: Always test SMTP connection before sending campaigns

License

© 2025 ProSendi. All rights reserved.