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.
Production: https://prosendi.com/api
Development: http://localhost:8000/api
All API requests require authentication using an API key. The API key must be:
The system automatically validates your API key on every request:
active field is trueexpires_dateIf any validation fails, the request is rejected with a 401 Unauthorized response.
Include your API key in one of the following ways:
X-API-Key: your_api_key_here
Authorization: Bearer your_api_key_here
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>"}'
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 |
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:
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"
}
]
}
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 messageSuccess 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 |
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]"
}
}
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"
}
}
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)Always include:
Content-Type: application/json
Accept: application/json
{
"success": false,
"message": "Human-readable error message",
"error": "error_code",
"data": {}
}
| 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 |
{
"success": false,
"message": "Quota exceeded",
"error": "quota_exceeded",
"data": {
"service_type": "email",
"requested": 10,
"remaining": 0,
"total_quota": 10000,
"usage_percentage": 100.0
}
}
{
"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."
}
}
Check your quota status:
Total Quota: 10,000 emails/month
Sent This Month: 7,500
Remaining: 2,500
Usage: 75%
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]"
}
);
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
$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);
?>
#!/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>"
Note: Webhooks are not yet implemented but planned for future releases.
Planned webhook events:
email.sent - Email sent successfullyemail.delivered - Email delivered to recipientemail.opened - Email opened by recipientemail.clicked - Link in email clickedemail.bounced - Email bounced (delivery failed)email.failed - Email failed to sendAlways 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);
}
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");
}
<html>, <head>, and <body> tagsUse variables to personalize emails:
const personalizedMessage = `
<html>
<body>
<h1>Hello ${firstName}!</h1>
<p>Thank you for joining us, ${fullName}.</p>
</body>
</html>
`;
© 2025 ProSendi. All rights reserved.