Send Email Messages
Send transactional and marketing emails to any recipient using YeboLink's email API — powered by Resend, with no SMTP setup required.
Endpoint
POST /api/v1/messages/sendAuthentication
Requires API Key authentication via X-API-Key header.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
to | string | Yes | Recipient email address (must be valid email format) |
channel | string | Yes | Must be "email" |
content | object | Yes | Message content object |
content.subject | string | Yes | Email subject line (required for email channel) |
content.html | string | Recommended | HTML body of the email |
content.text | string | No | Plain text fallback. If omitted and html is provided, recipients see HTML. |
content.reply_to | string | No | Email address recipient replies are routed to (must be a valid email format). Defaults to your workspace's account email if omitted. |
from | string | No | Sender display name shown in inbox (e.g. "KESHLESS", "MyApp"). Defaults to your workspace sender name. |
scheduled_at | string | No | ISO 8601 timestamp to send later instead of immediately — see Scheduling |
metadata | object | No | Custom key-value pairs for your own tracking |
The Idempotency-Key header is supported here too, making a retried email send safe from duplicates — see Idempotency.
Required Fields
For email channel: content.subject is required. At least one of content.html or content.text must be provided.
Sender Name
The from field sets the display name only. Emails always send from <name>@mail.yebolink.com. Contact support to use a custom domain.
Reply-To
Every email sends from the shared mail.yebolink.com address, so a recipient's "Reply" always needs somewhere real to land. Set content.reply_to to route replies to your own inbox — if you leave it out, YeboLink falls back to your workspace's account email so replies are never lost.
Try It Now
Send Email
Your API key is stored locally and never sent to our servers. Get an API key →
Example Request
curl -X POST https://api.yebolink.com/api/v1/messages/send \
-H "Content-Type: application/json" \
-H "X-API-Key: ybk_your_api_key" \
-d '{
"to": "user@example.com",
"channel": "email",
"content": {
"subject": "Your order is confirmed",
"html": "<h1>Order Confirmed ✓</h1><p>Thanks for your purchase. Your order #12345 is on its way.</p>",
"reply_to": "support@yourcompany.com"
},
"metadata": {
"user_id": "12345",
"order_id": "ORD-12345"
}
}'const sendEmail = async (to, subject, html, metadata = {}) => {
const response = await fetch('https://api.yebolink.com/api/v1/messages/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.YEBOLINK_API_KEY
},
body: JSON.stringify({
to,
channel: 'email',
content: { subject, html },
metadata
})
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.message);
}
return await response.json();
};
// Usage
const result = await sendEmail(
'user@example.com',
'Your order is confirmed',
'<h1>Order Confirmed ✓</h1><p>Your order #12345 is on its way.</p>',
{ order_id: 'ORD-12345' }
);
console.log('Message sent:', result.data.message_id);
console.log('Credits used:', result.data.credits_used);import os
import requests
def send_email(to: str, subject: str, html: str, metadata: dict = None):
response = requests.post(
'https://api.yebolink.com/api/v1/messages/send',
headers={'X-API-Key': os.environ.get('YEBOLINK_API_KEY')},
json={
'to': to,
'channel': 'email',
'content': {'subject': subject, 'html': html},
'metadata': metadata or {}
}
)
response.raise_for_status()
return response.json()
result = send_email(
to='user@example.com',
subject='Your order is confirmed',
html='<h1>Order Confirmed ✓</h1><p>Your order #12345 is on its way.</p>',
metadata={'order_id': 'ORD-12345'}
)
print(f"Message sent: {result['data']['message_id']}")
print(f"Credits used: {result['data']['credits_used']}")<?php
function sendEmail($to, $subject, $html, $metadata = []) {
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => 'https://api.yebolink.com/api/v1/messages/send',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-API-Key: ' . getenv('YEBOLINK_API_KEY')
],
CURLOPT_POSTFIELDS => json_encode([
'to' => $to,
'channel' => 'email',
'content' => ['subject' => $subject, 'html' => $html],
'metadata' => $metadata
])
]);
$response = curl_exec($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($httpCode !== 201) {
$error = json_decode($response, true);
throw new Exception($error['message']);
}
return json_decode($response, true);
}
$result = sendEmail(
'user@example.com',
'Your order is confirmed',
'<h1>Order Confirmed ✓</h1><p>Your order #12345 is on its way.</p>',
['order_id' => 'ORD-12345']
);
echo "Message sent: " . $result['data']['message_id'] . "\n";
echo "Credits used: " . $result['data']['credits_used'] . "\n";
?>package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
type EmailRequest struct {
To string `json:"to"`
Channel string `json:"channel"`
Content map[string]string `json:"content"`
Metadata map[string]string `json:"metadata,omitempty"`
}
func sendEmail(to, subject, html string, metadata map[string]string) (map[string]interface{}, error) {
payload := EmailRequest{
To: to,
Channel: "email",
Content: map[string]string{
"subject": subject,
"html": html,
},
Metadata: metadata,
}
jsonPayload, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", "https://api.yebolink.com/api/v1/messages/send", bytes.NewBuffer(jsonPayload))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", os.Getenv("YEBOLINK_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var result map[string]interface{}
json.Unmarshal(body, &result)
return result, nil
}
func main() {
result, err := sendEmail(
"user@example.com",
"Your order is confirmed",
"<h1>Order Confirmed ✓</h1><p>Your order #12345 is on its way.</p>",
map[string]string{"order_id": "ORD-12345"},
)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
data := result["data"].(map[string]interface{})
fmt.Printf("Message sent: %s\n", data["message_id"])
fmt.Printf("Credits used: %v\n", data["credits_used"])
}Response
Success (201 Created)
{
"success": true,
"data": {
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "queued",
"credits_used": "0.10",
"created_at": "2025-11-02T12:00:00Z"
}
}| Field | Type | Description |
|---|---|---|
message_id | string | Unique identifier for the message |
status | string | Always queued on creation |
credits_used | number | Credits deducted (0.1 per email) |
created_at | string | ISO 8601 timestamp |
Error Responses
Invalid Email Address (400)
{
"success": false,
"error": "validation_error",
"message": "Invalid email address format"
}Insufficient Credits (402)
{
"success": false,
"error": "insufficient_credits",
"message": "Not enough credits. You need 0.1 credits but have 0."
}Invalid API Key (401)
{
"success": false,
"error": "unauthorized",
"message": "Invalid or missing API key"
}Use Cases
Welcome Email
const sendWelcome = (email, name) => sendEmail(
email,
`Welcome to MyApp, ${name}!`,
`<h1>Welcome, ${name}!</h1>
<p>Your account is ready. <a href="https://myapp.com/dashboard">Get started →</a></p>`
);OTP / Verification
const sendOTP = (email, code) => sendEmail(
email,
'Your verification code',
`<p>Your code is: <strong style="font-size:24px">${code}</strong></p>
<p>Expires in 10 minutes. Do not share it.</p>`
);Order Confirmation
const sendOrderConfirmation = (email, order) => sendEmail(
email,
`Order #${order.id} confirmed`,
`<h2>Order Confirmed ✓</h2>
<p>Total: $${order.total}</p>
<p>Estimated delivery: ${order.deliveryDate}</p>
<a href="https://myapp.com/orders/${order.id}">Track your order →</a>`
);Invoice / Receipt
const sendInvoice = (email, invoice) => sendEmail(
email,
`Invoice #${invoice.number} from MyApp`,
`<h2>Invoice #${invoice.number}</h2>
<p>Amount due: $${invoice.amount}</p>
<p>Due date: ${invoice.dueDate}</p>
<a href="${invoice.pdfUrl}">Download PDF</a>`
);Password Reset
const sendPasswordReset = (email, resetLink) => sendEmail(
email,
'Reset your password',
`<p>Click below to reset your password. Link expires in 2 hours.</p>
<a href="${resetLink}" style="background:#6366f1;color:white;padding:12px 24px;border-radius:6px;text-decoration:none">
Reset Password
</a>
<p>If you didn't request this, ignore this email.</p>`
);Credits & Pricing
- Cost: 0.1 credits per email
- Delivery: Sent within seconds via Resend
- No volume limits beyond your credit balance
See Billing for credit packages and pricing.
Next Steps
- Send SMS Messages — Fast notifications, OTPs
- Send Bulk Messages — Send to thousands at once
- Setup Webhooks — Track delivery events
- Channels Overview — Compare all channels