Build with Pigeonify
Everything you need to integrate Pigeonify into your application.
Quick start guide
Send your first email
One HTTPS call, or standard SMTP if you already have a mail layer. Pick your language, paste it in, and swap the sending address for a domain you've verified.
curl -X POST https://www.pigeonify.com/api/v1/send \
-H "X-API-Key: $PIGEONIFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "You <hello@yourdomain.com>",
"to": "recipient@example.com",
"subject": "Hello from Pigeonify",
"html": "<strong>It works!</strong>"
}'Every example reads your key from PIGEONIFY_API_KEY rather than hardcoding it — an API key committed to a repository is a key you have to rotate. Create one under Dashboard → API Keys.
API documentation
Authentication
All API requests require an API key. You can generate API keys from your dashboard under Settings → API Keys.
Include your API key in the X-API-Key header:
X-API-Key: pgn_your_api_key_here
Send email
/api/v1/sendSend a single email through the Pigeonify API.
Request headers:
Content-Type: application/json X-API-Key: pgn_your_api_key_here
Request body:
{
"from": "noreply@yourdomain.com",
"to": "recipient@example.com",
"subject": "Hello from Pigeonify",
"html": "<h1>Hello!</h1><p>This is a test email.</p>",
"text": "Hello! This is a test email.",
"reply_to": "support@yourdomain.com"
}Optional fields: text, reply_to
Example request (cURL):
curl --location 'https://pigeonify.com/api/v1/send' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: pgn_your_api_key_here' \
--data-raw '{
"from": "noreply@yourdomain.com",
"to": "recipient@example.com",
"subject": "Hello from Pigeonify",
"html": "<h1>Hello!</h1><p>This is a test email.</p>",
"text": "Hello! This is a test email."
}'Success response (200):
{
"success": true,
"message": "Email sent successfully",
"sent": 2,
"suppressed": ["unsubscribed@example.com"]
}Recipients that have unsubscribed, hard bounced, or reported spam are skipped automatically and returned in suppressed. The rest of the batch is still delivered, and sent counts what actually went out. Manage the list under Suppressions in the dashboard.
Error responses:
{
"error": "Missing X-API-Key header"
}{
"error": "Missing required fields: from, to, subject, html"
}How to get your API key
- Log in to your Pigeonify dashboard
- Navigate to Dashboard → API Keys
- Click "Create API Key"
- Give your key a name (e.g., "Production API")
- Copy the generated key (it starts with
pgn_) - Store it securely — you won't be able to see it again!
SMTP configuration
SMTP settings
Use your personal SMTP credentials to send emails from your verified domains. Generate your credentials in the Settings → SMTP section.
TLS is required. Authentication is refused on an unencrypted connection, so your credentials are never sent in clear. On port 587 your client must issue STARTTLS before logging in — most do automatically, but set requireTLS or the equivalent if yours allows plaintext fallback. Port 465 is encrypted from the first byte.
Send only from verified domains. The address in your From header must be on a domain you have verified under Domains, or the message is refused with a 550.
Node.js example (Nodemailer):
const nodemailer = require('nodemailer');
const transporter = nodemailer.createTransport({
host: 'smtp.pigeonify.com',
port: 587,
secure: false, // STARTTLS on 587
requireTLS: true, // refuse to send if the upgrade fails
auth: {
user: 'smtp-12345678', // Your SMTP username
pass: 'your-smtp-password' // Your SMTP password
}
});
// Or, for implicit TLS:
// port: 465, secure: true (requireTLS is unnecessary)
await transporter.sendMail({
from: 'sender@yourdomain.com', // Must be a verified domain
to: 'recipient@example.com',
subject: 'Hello from Pigeonify',
html: '<h1>Hello World</h1>'
});Python example (smtplib):
import smtplib
from email.message import EmailMessage
msg = EmailMessage()
msg['Subject'] = 'Hello from Pigeonify'
msg['From'] = 'sender@yourdomain.com' # Must be a verified domain
msg['To'] = 'recipient@example.com'
msg.set_content('Hello World')
msg.add_alternative('<h1>Hello World</h1>', subtype='html')
# STARTTLS on 587
with smtplib.SMTP('smtp.pigeonify.com', 587) as server:
server.starttls()
server.login('smtp-12345678', 'your-smtp-password')
server.send_message(msg)
# Implicit TLS on 465
# with smtplib.SMTP_SSL('smtp.pigeonify.com', 465) as server:
# server.login('smtp-12345678', 'your-smtp-password')
# server.send_message(msg)What we add to your messages
Every message is signed with DKIM for your domain, and an unsubscribe link and the List-Unsubscribe headers are added automatically. Gmail and Yahoo require those headers from bulk senders, and we cannot tell a newsletter from a receipt over SMTP, so they are applied to everything.
Reply codes
A 5xx means the message will never be accepted as sent: an unverified sending domain, a recipient who has unsubscribed or is known undeliverable, or content our checks refused. Do not retry these.
A 4xx is temporary — a rate limit, a plan limit, or a problem at our end. Retry with backoff. Sending is limited to 100 messages per minute per account, with a per-second ceiling on top, so a client that paces itself will not see these.
Getting started:
- Go to Settings → SMTP in your dashboard
- Click "Generate SMTP Credentials" to create your credentials
- Copy your SMTP username and password (password shown only once)
- Verify a domain in the Domains section
- Use the credentials in your application to send emails
Domain setup
Verify your domain
To send emails from your domain, you need to verify it by adding DNS records:
- Go to Dashboard > Domains and add your domain
- Copy the provided DNS records (TXT, SPF, DKIM, DMARC)
- Add these records to your domain's DNS settings
- Click "Verify" to confirm the setup
Note: DNS changes can take up to 48 hours to propagate, but usually complete within a few hours.