Receive and read email
Find emails saved in SendHog and read their message details.
You can view saved emails in the dashboard email log or let your application read them through the API. Each API key can only access email for its own domain.
Give your application read access
Create an API key with the read-email permission, called email.read. A sending-only key cannot read emails. Then use the example below to find saved messages and open one.
The read methods are part of SendHog. They do not copy another provider’s incoming-email notifications, also known as webhooks.
import { SendHog } from '@sendhog/sdk';
const client = new SendHog(process.env.SENDHOG_API_KEY ?? '');
// SendHog extension shared by all provider variants.
// Requires a key with email.read scope.
const page = await client.messages.list({ direction: 'received', limit: 20 });
if (page.data.length) {
const message = await client.messages.get(page.data[0].id);
console.log(message.subject, message.text);
}npm install @sendhog/sdkimport { SendHog } from '@sendhog/sdk';
const client = new SendHog(process.env.SENDHOG_API_KEY ?? '');
// SendHog extension shared by all provider variants.
// Requires a key with email.read scope.
const page = await client.messages.list({ direction: 'received', limit: 20 });
if (page.data.length) {
const message = await client.messages.get(page.data[0].id);
console.log(message.subject, message.text);
}npm install @sendhog/sdkimport os
from sendhog import SendHog
client = SendHog(os.environ['SENDHOG_API_KEY'])
# SendHog extension; requires email.read scope.
page = client.messages.list(direction='received', limit=20)
if page['data']:
message = client.messages.get(page['data'][0]['id'])
print(message['subject'], message['text'])python -m pip install sendhog-sdkcurl 'https://app.sendhog.com/v1/messages?direction=received&limit=20' \
-H "Authorization: Bearer $SENDHOG_API_KEY"No SDK installation required.import { SESv2Client } from '@sendhog/sdk/ses';
const apiKey = process.env.SENDHOG_API_KEY;
if (!apiKey) throw new Error('Set SENDHOG_API_KEY on your server.');
const client = new SESv2Client({ apiKey });
// SendHog extension shared by all provider variants.
// Requires a key with email.read scope.
const page = await client.messages.list({ direction: 'received', limit: 20 });
if (page.data.length) {
const message = await client.messages.get(page.data[0].id);
console.log(message.subject, message.text);
}npm install @sendhog/sdkimport { SESv2Client } from '@sendhog/sdk/ses';
const apiKey = process.env.SENDHOG_API_KEY;
if (!apiKey) throw new Error('Set SENDHOG_API_KEY on your server.');
const client = new SESv2Client({ apiKey });
// SendHog extension shared by all provider variants.
// Requires a key with email.read scope.
const page = await client.messages.list({ direction: 'received', limit: 20 });
if (page.data.length) {
const message = await client.messages.get(page.data[0].id);
console.log(message.subject, message.text);
}npm install @sendhog/sdkimport os
from sendhog.ses import SESv2Client
client = SESv2Client(os.environ['SENDHOG_API_KEY'])
# SendHog extension; requires email.read scope.
page = client.messages.list(direction='received', limit=20)
if page['data']:
message = client.messages.get(page['data'][0]['id'])
print(message['subject'], message['text'])python -m pip install sendhog-sdkcurl 'https://app.sendhog.com/v1/messages?direction=received&limit=20' \
-H "Authorization: Bearer $SENDHOG_API_KEY"No SDK installation required.import { ServerClient } from '@sendhog/sdk/postmark';
const apiKey = process.env.SENDHOG_API_KEY;
if (!apiKey) throw new Error('Set SENDHOG_API_KEY on your server.');
const client = new ServerClient({ apiKey });
// SendHog extension shared by all provider variants.
// Requires a key with email.read scope.
const page = await client.messages.list({ direction: 'received', limit: 20 });
if (page.data.length) {
const message = await client.messages.get(page.data[0].id);
console.log(message.subject, message.text);
}npm install @sendhog/sdkimport { ServerClient } from '@sendhog/sdk/postmark';
const apiKey = process.env.SENDHOG_API_KEY;
if (!apiKey) throw new Error('Set SENDHOG_API_KEY on your server.');
const client = new ServerClient({ apiKey });
// SendHog extension shared by all provider variants.
// Requires a key with email.read scope.
const page = await client.messages.list({ direction: 'received', limit: 20 });
if (page.data.length) {
const message = await client.messages.get(page.data[0].id);
console.log(message.subject, message.text);
}npm install @sendhog/sdkimport os
from sendhog.postmark import ServerClient
client = ServerClient(os.environ['SENDHOG_API_KEY'])
# SendHog extension; requires email.read scope.
page = client.messages.list(direction='received', limit=20)
if page['data']:
message = client.messages.get(page['data'][0]['id'])
print(message['subject'], message['text'])python -m pip install sendhog-sdkcurl 'https://app.sendhog.com/v1/messages?direction=received&limit=20' \
-H "Authorization: Bearer $SENDHOG_API_KEY"No SDK installation required.import { Resend } from '@sendhog/sdk/resend';
const apiKey = process.env.SENDHOG_API_KEY;
if (!apiKey) throw new Error('Set SENDHOG_API_KEY on your server.');
const client = new Resend({ apiKey });
// SendHog extension shared by all provider variants.
// Requires a key with email.read scope.
const page = await client.messages.list({ direction: 'received', limit: 20 });
if (page.data.length) {
const message = await client.messages.get(page.data[0].id);
console.log(message.subject, message.text);
}npm install @sendhog/sdkimport { Resend } from '@sendhog/sdk/resend';
const apiKey = process.env.SENDHOG_API_KEY;
if (!apiKey) throw new Error('Set SENDHOG_API_KEY on your server.');
const client = new Resend({ apiKey });
// SendHog extension shared by all provider variants.
// Requires a key with email.read scope.
const page = await client.messages.list({ direction: 'received', limit: 20 });
if (page.data.length) {
const message = await client.messages.get(page.data[0].id);
console.log(message.subject, message.text);
}npm install @sendhog/sdkimport os
from sendhog.resend import Resend
client = Resend(os.environ['SENDHOG_API_KEY'])
# SendHog extension; requires email.read scope.
page = client.messages.list(direction='received', limit=20)
if page['data']:
message = client.messages.get(page['data'][0]['id'])
print(message['subject'], message['text'])python -m pip install sendhog-sdkcurl 'https://app.sendhog.com/v1/messages?direction=received&limit=20' \
-H "Authorization: Bearer $SENDHOG_API_KEY"No SDK installation required.import { SendGridClient } from '@sendhog/sdk/sendgrid';
const apiKey = process.env.SENDHOG_API_KEY;
if (!apiKey) throw new Error('Set SENDHOG_API_KEY on your server.');
const client = new SendGridClient({ apiKey });
// SendHog extension shared by all provider variants.
// Requires a key with email.read scope.
const page = await client.messages.list({ direction: 'received', limit: 20 });
if (page.data.length) {
const message = await client.messages.get(page.data[0].id);
console.log(message.subject, message.text);
}npm install @sendhog/sdkimport { SendGridClient } from '@sendhog/sdk/sendgrid';
const apiKey = process.env.SENDHOG_API_KEY;
if (!apiKey) throw new Error('Set SENDHOG_API_KEY on your server.');
const client = new SendGridClient({ apiKey });
// SendHog extension shared by all provider variants.
// Requires a key with email.read scope.
const page = await client.messages.list({ direction: 'received', limit: 20 });
if (page.data.length) {
const message = await client.messages.get(page.data[0].id);
console.log(message.subject, message.text);
}npm install @sendhog/sdkimport os
from sendhog.sendgrid import SendGridAPIClient
client = SendGridAPIClient(os.environ['SENDHOG_API_KEY'])
# SendHog extension; requires email.read scope.
page = client.messages.list(direction='received', limit=20)
if page['data']:
message = client.messages.get(page['data'][0]['id'])
print(message['subject'], message['text'])python -m pip install sendhog-sdkcurl 'https://app.sendhog.com/v1/messages?direction=received&limit=20' \
-H "Authorization: Bearer $SENDHOG_API_KEY"No SDK installation required.Find more messages
Messages are shown newest first. You can choose sent or received email and request more results a page at a time. An empty list means no matching saved messages were found; it does not confirm that incoming email is set up.
Technical options: set direction to sent or received. Set limit from 1–100; the default is 20. When has_more is true, pass the returned next_cursor as after for the next page. Keep that cursor unchanged—it marks your place in the list, not an API key.
Messages with the same timestamp are ordered by ID. A missing message ID and an ID belonging to another domain both return 404.
What you can read
The list shows basic details such as sender, recipient and subject. Open a message to read its saved plain-text content. Attachments, the original email file and the HTML version are not available through this API.
Technical limits: list entries have text: null. Message details can contain up to 100,000 characters of plain text. Subjects are limited to 2,000 characters, sender details to 1,024 and recipient details to 16,000. A page may be shorter than requested to keep the response small; follow next_cursor if more results are available.
Messages that were not saved cannot be recovered through this API. See the API reference for the full list of fields.