Email and the messages API
Understand why Samva exposes both an email send facade and a messages API, and how each fits your integration.
Use email.send() for TypeScript email integrations. It sends through the same endpoint as
messages.send(), which mirrors the channel-aware body of POST /v1/messages. Both support
contact IDs, multiple recipients, and conversation replies. The difference is the request shape.
Two shapes, one pipeline
Underneath, every send Samva performs is a message: recipients, content, and the channel it goes
out on, email. The messages API names those parts explicitly. When you call messages.send(), you
set channel: "email", list your recipients in to, and nest the email content under email:
import { createClient } from "samva";
const samva = createClient({ apiKey: process.env.SAMVA_API_KEY! });
await samva.messages.send({
to: [{ contactId: "contact_k9mvt4znw8rh7q2x" }],
cc: [{ email: "grace@example.com" }],
channel: "email",
email: {
subject: "Welcome to Samva",
html: "<h1>Welcome!</h1><p>Thanks for joining.</p>",
replyTo: "support@example.com",
},
});The email.send() facade is the same call in an email-shaped form. It sets the channel for you,
flattens the email content up to the top level of the input, and accepts a single recipient or an
array. The result is a call that reads like sending an email rather than configuring a generic
message:
import { createClient } from "samva";
const samva = createClient({ apiKey: process.env.SAMVA_API_KEY! });
const result = await samva.email.send({
to: "ada@example.com",
cc: "grace@example.com",
replyTo: "support@example.com",
subject: "Welcome to Samva",
html: "<h1>Welcome!</h1>",
});There is no separate email.send HTTP endpoint. The facade is an SDK-only ergonomic wrapper: it
builds the message body shape for you and posts it to POST /v1/messages. From the server's point of
view, both snippets above reach the same endpoint. The difference lives entirely in
the SDK, in service of the developer reading the code.
Why a facade at all
Most email you send is straightforward. You have an address, a subject, and some HTML, and you want
the call site to say exactly that. Forcing every send to spell out channel: "email" and nest content
under an email: key adds ceremony to the common case without adding meaning; the channel is obvious
when you reached for email.send().
The facade optimizes for that common case. Flattening the email fields directly into the SDK input keeps the simple path short and removes a layer of nesting you would otherwise repeat on every send. It is the canonical way to send a one-off transactional email, and it is what the send an email guide walks through.
The facade supports the email fields available through the messages API, including attachments,
contact recipients, cc, bcc, and conversationId. You can keep using email.send() as your
email integration grows.
When to use a channel-aware body
Use messages.send() when your application already holds a channel-aware message body, or when
code selects the channel and its content together. The method keeps the HTTP request shape visible:
channel, recipient arrays, and content under the channel key. For email-specific code,
email.send() keeps that same content at the top level.
REST is always the message shape
The split between a facade and the messages API is an SDK convenience. It does not exist over the wire.
Every REST integration, whether or not you use the TypeScript SDK, sends to POST /v1/messages
using the message body: a channel, a to array, and channel content nested under its key. If you
are calling the API directly, there is one shape to learn, and the SDK's email.send() is simply
producing that shape on your behalf.
This is why the REST reference and the TypeScript SDK reference can describe the same capability from two angles without contradiction: one documents the endpoint, the other documents the ergonomics layered over it.
Related
Related documentation
How Samva works
Understand how a send flows from your code to the inbox, the core objects that model email, and the single-API philosophy behind Samva.
Organizations and tenancy
Understand how a Samva credential binds to an organization, why every record is tenant-scoped, and how teams and usage share that boundary.