POST
/
api
/
v2
/
emails
/
{id}
/
reply
import { Inbound } from '@inboundemail/sdk';

const inbound = new Inbound('YOUR_API_KEY');

const { data, error } = await inbound.reply('email_abc123', {
  from: 'support@yourdomain.com',
  text: 'Thank you for your email. We have received your request and will respond shortly.'
});

if (error) {
  console.error('Error:', error);
} else {
  console.log('Reply sent:', data.id);
}
{
  "id": "sent_xyz789",
  "messageId": "xyz789@yourdomain.com",
  "awsMessageId": "0100018e1234abcd-12345678-1234-1234-1234-123456789012-000000"
}
This endpoint allows you to reply to emails received through Inbound, maintaining proper email threading with In-Reply-To and References headers.

Authentication

This endpoint requires authentication via:
  • API key auth: Bearer token in Authorization header

Path Parameters

id
string
required
The unique identifier of the email you want to reply to. This must be an email that was received through your Inbound account.

Request Body

This endpoint supports both snake_case (legacy) and camelCase (Resend-compatible) formats for certain fields like reply_to/replyTo and include_original/includeOriginal.
from
string
required
The sender email address. Must be in the format "Name <email@domain.com>" or just "email@domain.com". The domain must be verified in your account.
from_name
string
Optional sender name for display. If provided, this will be used as the display name for the sender address.
to
string | string[]
The recipient email address(es). If not provided, the reply will be sent to the original sender. Can be a single email string or an array of email strings.
subject
string
The email subject. If not provided, “Re: ” will be prepended to the original email’s subject.
cc
string | string[]
Carbon copy recipient(s). Can be a single email string or an array of email strings.
bcc
string | string[]
Blind carbon copy recipient(s). Can be a single email string or an array of email strings.
reply_to
string | string[]
Reply-to address(es). Can be a single email string or an array of email strings. Also accepts replyTo (camelCase) for Resend compatibility.
text
string
The plain text version of the email body. Either text or html must be provided.
html
string
The HTML version of the email body. Either text or html must be provided.
headers
object
Custom email headers as key-value pairs. These will be added to the email in addition to the standard headers.
attachments
array
Array of file attachments to include with the email.
include_original
boolean
default:"true"
Whether to include the original message as a quoted reply. When true, the original message will be appended to your reply with appropriate formatting. Also accepts includeOriginal (camelCase) for Resend compatibility.
tags
array
Array of tags for email categorization and tracking (Resend-compatible).
simple
boolean
default:"true"
Whether to use simplified reply mode for faster processing. When true (default), uses a lightweight reply mode that’s faster and has less overhead. Set to false to force full mode when you need advanced features or custom threading.
Simple mode is automatically disabled when attachments are present.

Headers

Authorization
string
required
Bearer token for API authentication.
Idempotency-Key
string
Add an idempotency key to prevent duplicate replies.
  • Should be unique per API request
  • Idempotency keys expire after 24 hours
  • Have a maximum length of 256 characters

Response

id
string
required
Unique identifier for the sent reply email in Inbound’s system
messageId
string
required
The Inbound message ID used for email threading (appears in Message-ID header)
awsMessageId
string
AWS SES Message ID for tracking the email through AWS infrastructure. Only present when the email is successfully sent through AWS SES.

Email Threading

This endpoint automatically handles email threading by:
  1. Setting the In-Reply-To header with the Message-ID of the original email
  2. Building the References header to maintain the full conversation thread
  3. Formatting the subject with “Re: ” prefix if not already present
  4. Quoting the original message (when include_original is true) with proper attribution
Email clients like Gmail, Outlook, and Apple Mail will recognize these threading headers and group the emails into a conversation.

Examples

Basic Reply

Reply to an email with minimal configuration:
import { Inbound } from '@inboundemail/sdk';

const inbound = new Inbound('YOUR_API_KEY');

const { data, error } = await inbound.reply('email_abc123', {
  from: 'support@yourdomain.com',
  text: 'Thank you for your email. We have received your request and will respond shortly.'
});

if (error) {
  console.error('Error:', error);
} else {
  console.log('Reply sent:', data.id);
}
{
  "id": "sent_xyz789",
  "messageId": "xyz789@yourdomain.com",
  "awsMessageId": "0100018e1234abcd-12345678-1234-1234-1234-123456789012-000000"
}

Advanced Reply with Custom Recipients

Reply with custom recipients, subject, HTML content, and tags:
import { Inbound } from '@inboundemail/sdk';

const inbound = new Inbound('YOUR_API_KEY');

const { data, error } = await inbound.reply('email_abc123', {
  from: 'john@yourdomain.com',
  to: ['customer@example.com'],
  cc: ['manager@yourdomain.com'],
  subject: 'Re: Support Request #12345',
  text: 'Dear Customer,\n\nWe have resolved your issue...',
  html: '<p>Dear Customer,</p><p>We have resolved your issue...</p>',
  headers: {
    'X-Support-Ticket': '12345'
  },
  includeOriginal: true,
  tags: [
    { name: 'category', value: 'support' },
    { name: 'priority', value: 'high' }
  ]
});

Reply Without Quoting Original

Send a reply without including the original message:
import { Inbound } from '@inboundemail/sdk';

const inbound = new Inbound('YOUR_API_KEY');

const { data, error } = await inbound.reply('email_abc123', {
  from: 'noreply@yourdomain.com',
  text: 'This is an automated response.',
  includeOriginal: false
});

Reply with Attachments

Include attachments in your reply:
import { Inbound } from '@inboundemail/sdk';
import fs from 'fs';

const inbound = new Inbound('YOUR_API_KEY');

// Read and encode file
const fileContent = fs.readFileSync('invoice.pdf');
const base64Content = fileContent.toString('base64');

const { data, error } = await inbound.reply('email_abc123', {
  from: 'billing@yourdomain.com',
  text: 'Please find the invoice attached.',
  attachments: [{
    content: base64Content,
    filename: 'invoice.pdf',
    content_type: 'application/pdf'
  }]
});

Error Responses

error
string
Error message describing what went wrong

Common Errors

Status CodeError MessageDescription
400”Valid email ID is required”The email ID parameter is missing or invalid
400”From address is required”The from field is missing from the request
400”Either html or text content must be provided”No email body content was provided
400”Cannot determine recipient email address”No to field provided and cannot extract from original email
400”Invalid email format: One of the email addresses is malformed
400”Invalid JSON in request body”Request body contains malformed JSON
401”Unauthorized”Invalid or missing API key
403”You don’t have permission to send from domain: The sender domain is not verified in your account
404”Email not found”The email ID does not exist or belongs to another user
429”Email sending limit reached. Please upgrade your plan to send more emails.”You have exceeded your plan’s email sending limit
500”Email service not configured. Please contact support.”AWS SES configuration issue
500”Failed to send reply. Please try again later.”AWS SES or other service error occurred
500”Internal server error”An unexpected error occurred
{
  "error": "You don't have permission to send from domain: unverified.com"
}

Idempotency

This endpoint supports idempotency to prevent duplicate sends. Include an Idempotency-Key header with a unique value:

Basic Idempotency Usage

import { Inbound } from '@inboundemail/sdk';

const inbound = new Inbound('YOUR_API_KEY');

// Using the organized API with idempotency
const { data, error } = await inbound.email.sent.reply('email_abc123', {
  from: 'support@yourdomain.com',
  text: 'Thanks for your message!'
}, {
  idempotencyKey: 'reply-abc123-user456-v1'
});

// Using the simplified reply method with idempotency
const { data, error } = await inbound.reply('email_abc123', {
  from: 'support@yourdomain.com',
  text: 'Your reply message'
}, {
  idempotencyKey: 'unique-key-123'
});

Webhook Handler with Idempotency

Perfect for preventing duplicate auto-replies when webhooks are retried:
import { Inbound } from '@inboundemail/sdk';

const inbound = new Inbound(process.env.INBOUND_API_KEY);

// Webhook handler with idempotency protection
export async function POST(request) {
  try {
    const { email } = await request.json();
    
    // Create unique key that prevents duplicates even with webhook retries
    const idempotencyKey = `auto-reply-${email.id}-${Math.floor(Date.now() / 60000)}`;
    
    const { data, error } = await inbound.reply(email.id, {
      from: 'support@yourdomain.com',
      text: 'Thanks for contacting us! We\'ll respond within 24 hours.',
      includeOriginal: false
    }, {
      idempotencyKey
    });
    
    if (error) {
      console.error('Auto-reply failed:', error);
      return Response.json({ error: 'Failed to send auto-reply' }, { status: 500 });
    }
    
    return Response.json({ success: true, emailId: data.id });
    
  } catch (error) {
    return Response.json({ error: 'Processing failed' }, { status: 500 });
  }
}

Idempotency Key Best Practices

1

Make keys unique and descriptive

Include action type, email ID, and context: reply-{emailId}-{userId}-v1
2

Use for webhook handlers

Prevent duplicate auto-replies when webhooks are retried due to failures
3

Include version suffixes

Add -v1, -v2 when you need to update email content for the same operation
4

Consider time windows

For time-sensitive operations, include timestamp to allow periodic updates
Idempotency Behavior: If you make multiple requests with the same idempotency key, only the first request will send an email. Subsequent requests return the same response without sending a duplicate. Keys expire after 24 hours.

Best Practices

1

Verify sender domain

Always ensure the from domain is verified in your account before attempting to send replies.
2

Include both text and HTML

For best compatibility, include both text and html versions of your email content.
3

Use idempotency keys

When sending replies programmatically, use idempotency keys to prevent accidental duplicate sends.
4

Handle quoted content carefully

Consider whether including the original message is appropriate for your use case. Automated responses might not need it.
5

Test threading

Test your replies with various email clients to ensure threading works as expected.

Rate Limits

Reply sending is subject to the same rate limits as the Send Email endpoint. Your plan determines how many emails you can send per month.
Check your current usage and limits in your account dashboard.
1.0 - ✅