Skip to content

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/send

Authentication ​

Requires API Key authentication via X-API-Key header.

Request Body ​

ParameterTypeRequiredDescription
tostringYesRecipient email address (must be valid email format)
channelstringYesMust be "email"
contentobjectYesMessage content object
content.subjectstringYesEmail subject line (required for email channel)
content.htmlstringRecommendedHTML body of the email
content.textstringNoPlain text fallback. If omitted and html is provided, recipients see HTML.
content.reply_tostringNoEmail address recipient replies are routed to (must be a valid email format). Defaults to your workspace's account email if omitted.
fromstringNoSender display name shown in inbox (e.g. "KESHLESS", "MyApp"). Defaults to your workspace sender name.
scheduled_atstringNoISO 8601 timestamp to send later instead of immediately — see Scheduling
metadataobjectNoCustom 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 ​

bash
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": "[email protected]",
    "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": "[email protected]"
    },
    "metadata": {
      "user_id": "12345",
      "order_id": "ORD-12345"
    }
  }'
javascript
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(
  '[email protected]',
  '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);
python
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='[email protected]',
    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
<?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(
    '[email protected]',
    '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";
?>
go
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(
        "[email protected]",
        "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) ​

json
{
  "success": true,
  "data": {
    "message_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "queued",
    "credits_used": "0.10",
    "created_at": "2025-11-02T12:00:00Z"
  }
}
FieldTypeDescription
message_idstringUnique identifier for the message
statusstringAlways queued on creation
credits_usednumberCredits deducted (0.1 per email)
created_atstringISO 8601 timestamp

Error Responses ​

Invalid Email Address (400) ​

json
{
  "success": false,
  "error": "validation_error",
  "message": "Invalid email address format"
}

Insufficient Credits (402) ​

json
{
  "success": false,
  "error": "insufficient_credits",
  "message": "Not enough credits. You need 0.1 credits but have 0."
}

Invalid API Key (401) ​

json
{
  "success": false,
  "error": "unauthorized",
  "message": "Invalid or missing API key"
}

Use Cases ​

Welcome Email ​

javascript
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 ​

javascript
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 ​

javascript
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 ​

javascript
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 ​

javascript
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 ​

Built with VitePress