PappyMail API
Powerful email sending API for developers. Integrate in minutes with official SDKs for Node.js, Python, .NET & more.
Base URL: https://pappymall.com/api/v1 — camelCase JSON bodies
Built for production email
Send emails in milliseconds with our optimized infrastructure
Enterprise-grade security with 99.9% uptime guarantee
Track deliveries, opens, clicks, and more
Up & running in 3 steps
Sign up and navigate to IT Department → Email System → API Keys to generate your key.
Add and verify your sending domain in IT Department → Email Domains.
Use the code examples below to send your first email with any language.
Endpoints
/api/v1/mail/send
Send Email
Send a single email to one or more recipients.
Authentication
Include your API key in the request header:
Authorization: Bearer YOUR_API_KEY
Or:
X-API-Key: YOUR_API_KEY
Request Body
Property names are camelCase (e.g. html_content, message_id in responses).
{
"from": {
"email": "sender@yourdomain.com",
"name": "Your Name"
},
"to": [
{
"email": "recipient@example.com",
"name": "Recipient Name"
}
],
"subject": "Your email subject",
"html_content": "<h1>Hello World</h1><p>This is a test email.</p>",
"text_content": "Hello World. This is a test email."
}
Response
{
"message_id": "msg_abc123xyz",
"status": "queued",
"message": "Email queued for delivery"
}
/api/v1/mail/stats
Get API Usage Statistics
Retrieve your current API usage and limits.
Response
{
"daily_usage": 150,
"daily_limit": 1000,
"monthly_usage": 3500,
"monthly_limit": 50000,
"last_used": "2025-11-09T10:30:00Z",
"reset_date": "2025-11-09T00:00:00Z"
}
Send email in your language
curl -X POST https://pappymall.com/api/v1/mail/send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": {
"email": "sender@yourdomain.com",
"name": "Your Name"
},
"to": [
{
"email": "recipient@example.com",
"name": "Recipient"
}
],
"subject": "Hello from PappyMail",
"html_content": "Hello World
This is a test email.
"
}'
SDK libraries & implementation
Node.js / JavaScript
npm install @pappymall/mail
# or
yarn add @pappymall/mail
const { PappyMail } = require('@pappymall/mail');
// Initialize the client
const client = new PappyMail({
apiKey: 'pm_live_your_api_key',
baseUrl: 'https://pappymall.com/api/v1'
});
// Send a simple email
await client.sendSimple({
from: 'noreply@yourdomain.com',
to: 'customer@example.com',
subject: 'Welcome to Our Service',
html: '<h1>Welcome!</h1><p>Thank you for signing up.</p>'
});
console.log('Email sent!');
const { PappyMail } = require('@pappymall/mail');
const client = new PappyMail({
apiKey: 'pm_live_your_api_key',
baseUrl: 'https://pappymall.com/api/v1',
timeout: 30000, // 30 second timeout
maxRetries: 3 // Retry failed requests
});
// Send email with full options
const response = await client.mail.send({
from: { email: 'noreply@yourdomain.com', name: 'Your App' },
to: [{ email: 'customer@example.com', name: 'Customer Name' }],
cc: [{ email: 'manager@example.com' }],
subject: 'Welcome to Our Service',
html_content: '<h1>Welcome!</h1><p>Thank you for signing up.</p>',
text_content: 'Welcome! Thank you for signing up.'
});
console.log('Message ID:', response.message_id);
console.log('Status:', response.status);
// Get API usage stats
const stats = await client.stats.getGlobal();
console.log('Daily usage:', stats.daily_usage, '/', stats.daily_limit);
// Manage templates
const templates = await client.templates.list();
console.log('Templates:', templates.data.length);
// Create a template
const template = await client.templates.create({
name: 'Welcome Email',
html_content: '<h1>Welcome!</h1>'
});
// Manage domains
const domains = await client.domains.list();
console.log('Domains:', domains.data.length);
// Webhooks
const webhook = await client.webhooks.create(
'https://yourapp.com/webhooks/email',
['delivered', 'opened', 'clicked', 'bounced']
);
// Verify webhook signatures (X-PappyMail-Signature: sha256=<hex>)
const isValid = PappyMail.verifyWebhookSignature(rawBody, signatureHeader, webhook.secret);
// Equivalent: WebhooksClient.verifySignature(rawBody, signatureHeader, webhook.secret)
const { PappyMail, ValidationError, RateLimitError, PappyMailError } = require('@pappymall/mail');
try {
await client.mail.send({ /* ... */ });
} catch (error) {
if (error instanceof ValidationError) {
console.error('Validation error:', error.message);
error.details?.forEach(d => console.error(` - ${d.field}: ${d.message}`));
} else if (error instanceof RateLimitError) {
console.error('Rate limited. Retry after:', error.retryAfter, 'seconds');
} else if (error instanceof PappyMailError) {
console.error(`Error [${error.code}]:`, error.message);
}
}
Python
pip install pappymail
import asyncio
from pappymail import PappyMail, PappyMailOptions
async def main():
opts = PappyMailOptions(
api_key="pm_live_your_api_key",
base_url="https://pappymall.com/api/v1",
)
async with PappyMail(opts) as client:
r = await client.send_simple(
from_email="noreply@yourdomain.com",
to="customer@example.com",
subject="Welcome to Our Service",
html="<h1>Welcome!</h1><p>Thank you for signing up.</p>",
)
print(r.message_id)
asyncio.run(main())
# Raw body string + X-PappyMail-Signature header + webhook secret
ok = PappyMail.verify_webhook_signature(payload, signature_header, secret)
Models use camelCase on the wire; use PappyMailOptions to set base_url for this host.
Go
# No external dependencies needed for basic HTTP client
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
type PappyMailClient struct {
APIKey string
BaseURL string
}
type EmailRecipient struct {
Email string `json:"email"`
Name string `json:"name,omitempty"`
}
type SendEmailRequest struct {
From EmailRecipient `json:"from"`
To []EmailRecipient `json:"to"`
Subject string `json:"subject"`
HTMLContent string `json:"html_content,omitempty"`
TextContent string `json:"text_content,omitempty"`
CC []EmailRecipient `json:"cc,omitempty"`
BCC []EmailRecipient `json:"bcc,omitempty"`
}
type SendEmailResponse struct {
MessageID string `json:"message_id"`
Status string `json:"status"`
Message string `json:"message"`
}
func NewPappyMailClient(apiKey string) *PappyMailClient {
return &PappyMailClient{
APIKey: apiKey,
BaseURL: "https://pappymall.com/api/v1/mail",
}
}
func (c *PappyMailClient) SendEmail(req SendEmailRequest) (*SendEmailResponse, error) {
jsonData, err := json.Marshal(req)
if err != nil {
return nil, fmt.Errorf("failed to marshal request: %w", err)
}
httpReq, err := http.NewRequest("POST", c.BaseURL+"/send", bytes.NewBuffer(jsonData))
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
httpReq.Header.Set("Authorization", "Bearer "+c.APIKey)
httpReq.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(httpReq)
if err != nil {
return nil, fmt.Errorf("failed to send request: %w", err)
}
defer resp.Body.Close()
var result SendEmailResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, fmt.Errorf("failed to decode response: %w", err)
}
return &result, nil
}
// Usage Example
func main() {
client := NewPappyMailClient("pm_live_your_api_key")
result, err := client.SendEmail(SendEmailRequest{
From: EmailRecipient{
Email: "noreply@yourdomain.com",
Name: "Your App",
},
To: []EmailRecipient{
{Email: "customer@example.com", Name: "Customer Name"},
},
Subject: "Welcome to Our Service",
HTMLContent: "<h1>Welcome!</h1><p>Thank you for signing up.</p>",
})
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Email sent: %s\n", result.MessageID)
}
.NET / C#
dotnet add package PappyMail.SDK
# or
Install-Package PappyMail.SDK
using PappyMail.SDK.Client;
// Initialize the client
var client = new PappyMailClient(new PappyMailClientOptions
{
ApiKey = "pm_live_your_api_key"
});
// Send a simple email
await client.SendAsync(
from: "noreply@yourdomain.com",
to: "customer@example.com",
subject: "Welcome to Our Service",
html: "<h1>Welcome!</h1><p>Thank you for signing up.</p>"
);
Console.WriteLine("Email sent!");
using PappyMail.SDK.Client;
using PappyMail.SDK.Models;
var client = new PappyMailClient(new PappyMailClientOptions
{
ApiKey = "pm_live_your_api_key",
BaseUrl = "https://pappymall.com/api/v1",
TimeoutSeconds = 30,
MaxRetries = 3,
EnableLogging = true
});
// Send email with full options
var response = await client.Mail.SendAsync(new SendEmailRequest
{
From = new EmailAddress("noreply@yourdomain.com", "Your App"),
To = new List<EmailAddress> { new("customer@example.com", "Customer Name") },
Cc = new List<EmailAddress> { new("manager@example.com") },
Subject = "Welcome to Our Service",
HtmlContent = "<h1>Welcome!</h1><p>Thank you for signing up.</p>",
TextContent = "Welcome! Thank you for signing up."
});
Console.WriteLine($"Message ID: {response.MessageId}");
Console.WriteLine($"Status: {response.Status}");
// Get API usage stats
var stats = await client.Stats.GetGlobalAsync();
Console.WriteLine($"Daily usage: {stats.DailyUsage}/{stats.DailyLimit}");
// Manage templates
var templates = await client.Templates.ListAsync();
Console.WriteLine($"Templates: {templates.Data.Count}");
// Create a template
var template = await client.Templates.CreateAsync(new CreateTemplateRequest
{
Name = "Welcome Email",
HtmlContent = "<h1>Welcome!</h1>"
});
// Manage domains
var domains = await client.Domains.ListAsync();
Console.WriteLine($"Domains: {domains.Data.Count}");
// Webhooks
var webhook = await client.Webhooks.CreateAsync(
"https://yourapp.com/webhooks/email",
new List<string> { "delivered", "opened", "clicked", "bounced" }
);
// Verify webhook signatures
var isValid = WebhooksClient.VerifySignature(
payload,
signature,
webhook.Secret
);
using PappyMail.SDK.Exceptions;
try
{
await client.Mail.SendAsync(new SendEmailRequest { /* ... */ });
}
catch (ValidationException ex)
{
Console.WriteLine($"Validation error: {ex.Message}");
foreach (var detail in ex.Details ?? new List<ErrorDetail>())
{
Console.WriteLine($" - {detail.Field}: {detail.Message}");
}
}
catch (RateLimitException ex)
{
Console.WriteLine($"Rate limited. Retry after: {ex.RetryAfter} seconds");
}
catch (UnauthorizedException)
{
Console.WriteLine("Invalid API key");
}
catch (PappyMailException ex)
{
Console.WriteLine($"Error [{ex.ErrorCode}]: {ex.Message}");
}
Supports .NET 6.0, 7.0, 8.0, and 9.0
PHP
# Requires PHP 7.4+ with cURL extension enabled
<?php
class PappyMailClient
{
private $apiKey;
private $baseURL = 'https://pappymall.com/api/v1/mail';
public function __construct($apiKey)
{
$this->apiKey = $apiKey;
}
public function sendEmail($data)
{
$ch = curl_init($this->baseURL . '/send');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
],
CURLOPT_POSTFIELDS => json_encode($data)
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 202) {
throw new Exception('PappyMail API Error: ' . $response);
}
return json_decode($response, true);
}
public function getStats()
{
$ch = curl_init($this->baseURL . '/stats');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->apiKey
]
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new Exception('PappyMail API Error: ' . $response);
}
return json_decode($response, true);
}
}
// Usage Example
$client = new PappyMailClient('pm_live_your_api_key');
try {
$result = $client->sendEmail([
'from' => ['email' => 'noreply@yourdomain.com', 'name' => 'Your App'],
'to' => [['email' => 'customer@example.com', 'name' => 'Customer Name']],
'subject' => 'Welcome to Our Service',
'html_content' => '<h1>Welcome!</h1><p>Thank you for signing up.</p>'
]);
echo "Email sent: " . $result['message_id'];
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
?>
React / Next.js
npm install @pappymall/mail
# or
yarn add @pappymall/mail
// hooks/usePappyMail.js
import { useState, useCallback } from 'react';
import { PappyMail, PappyMailError } from '@pappymall/mail';
export const usePappyMail = (apiKey) => {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
// Initialize client once
const client = new PappyMail({
apiKey,
baseUrl: 'https://pappymall.com/api/v1'
});
const sendEmail = useCallback(async (emailData) => {
setLoading(true);
setError(null);
try {
const response = await client.mail.send({
from: emailData.from,
to: emailData.to,
subject: emailData.subject,
html_content: emailData.htmlContent,
text_content: emailData.textContent,
cc: emailData.cc,
bcc: emailData.bcc
});
setLoading(false);
return response;
} catch (err) {
const errorMessage = err instanceof PappyMailError
? err.message
: 'An error occurred';
setError(errorMessage);
setLoading(false);
throw err;
}
}, [client]);
const getStats = useCallback(async () => {
try {
return await client.stats.getGlobal();
} catch (err) {
throw err;
}
}, [client]);
return { sendEmail, getStats, loading, error };
};
// Usage in Component
import React, { useState } from 'react';
import { usePappyMail } from './hooks/usePappyMail';
export default function EmailForm() {
const { sendEmail, loading, error } = usePappyMail('pm_live_your_api_key');
const [status, setStatus] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
try {
const result = await sendEmail({
from: { email: 'noreply@yourdomain.com', name: 'Your App' },
to: [{ email: 'customer@example.com', name: 'Customer' }],
subject: 'Welcome to Our Service',
htmlContent: '<h1>Welcome!</h1><p>Thank you for signing up.</p>'
});
setStatus(`Email sent! ID: ${result.message_id}`);
} catch (err) {
setStatus(`Error: ${error}`);
}
};
return (
<form onSubmit={handleSubmit}>
<button type="submit" disabled={loading}>
{loading ? 'Sending...' : 'Send Email'}
</button>
{status && <p>{status}</p>}
</form>
);
}
// pages/api/send-email.js
import { PappyMail } from '@pappymall/mail';
const client = new PappyMail({
apiKey: process.env.PAPPYMAIL_API_KEY, // Store in .env.local
baseUrl: 'https://pappymall.com/api/v1'
});
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
const response = await client.mail.send({
from: req.body.from,
to: req.body.to,
subject: req.body.subject,
html_content: req.body.htmlContent,
text_content: req.body.textContent
});
res.status(200).json({
success: true,
messageId: response.message_id
});
} catch (error) {
console.error('Email sending failed:', error.response?.data || error.message);
res.status(500).json({
success: false,
error: error.response?.data?.message || 'Failed to send email'
});
}
}
// Usage in component:
// const response = await fetch('/api/send-email', {
// method: 'POST',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify(emailData)
// });
@pappymall/mail above):
// lib/pappymail.ts — example only; production apps should use @pappymall/mail
import axios, { AxiosError } from 'axios';
interface EmailRecipient {
email: string;
name?: string;
}
interface SendEmailRequest {
from: EmailRecipient;
to: EmailRecipient[];
subject: string;
htmlContent?: string;
textContent?: string;
cc?: EmailRecipient[];
bcc?: EmailRecipient[];
}
interface SendEmailResponse {
message_id: string;
status: string;
message: string;
}
export class PappyMailClient {
private apiKey: string;
private baseURL: string = 'https://pappymall.com/api/v1/mail';
constructor(apiKey: string) {
this.apiKey = apiKey;
}
async sendEmail(data: SendEmailRequest): Promise<SendEmailResponse> {
try {
const response = await axios.post<SendEmailResponse>(
`${this.baseURL}/send`,
{
from: data.from,
to: data.to,
subject: data.subject,
html_content: data.htmlContent,
text_content: data.textContent,
cc: data.cc,
bcc: data.bcc
},
{
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
}
}
);
return response.data;
} catch (error) {
const axiosError = error as AxiosError<{ message: string }>;
throw new Error(
axiosError.response?.data?.message ||
axiosError.message
);
}
}
async getStats() {
const response = await axios.get(`${this.baseURL}/stats`, {
headers: {
'Authorization': `Bearer ${this.apiKey}`
}
});
return response.data;
}
}
// Usage
const client = new PappyMailClient(process.env.NEXT_PUBLIC_PAPPYMAIL_API_KEY!);
const result = await client.sendEmail({
from: { email: 'noreply@yourdomain.com', name: 'Your App' },
to: [{ email: 'customer@example.com', name: 'Customer Name' }],
subject: 'Welcome',
htmlContent: '<h1>Hello!</h1>'
});
Quick Reference
| Language | Package / approach | Install |
|---|---|---|
| Node.js | Official @pappymall/mail |
npm install @pappymall/mail (v1.0.2) |
| Python | Official pappymail (async, httpx) |
pip install pappymail (v1.0.0) |
| Go | net/http (built-in) |
No SDK — use REST directly |
| .NET | Official PappyMail.SDK |
dotnet add package PappyMail.SDK (v1.0.1) |
| PHP | cURL (built-in) |
No SDK — use REST directly |
| React/Next.js | Official @pappymall/mail (server or API routes) |
npm install @pappymall/mail |
Ready to start sending?
Join developers using PappyMail API to deliver transactional email at scale.