TypeScript SDK

Reference for the samva TypeScript SDK, covering client setup, the email send facade, every service namespace, errors, and the native Effect client.

The samva package is the official TypeScript SDK for the Samva API. It is generated from the OpenAPI document the API publishes, so every method matches the operation it calls and covers the whole public API.

This page is a reference. For a step-by-step first send, see Send your first email.

Installation

npm install samva

Entrypoints

ImportStyleWhen to use
samvaPromise (default)Most apps.
samva/promisesPromise (explicit)The same client as the root; use it when the same file also imports samva/effect.
samva/effect/*Native Effect v4Effect applications. One module per namespace, plus client. Requires effect as a peer dependency.
samva/webhooksPromiseVerify and decode signed webhook deliveries. samva/webhooks/effect is the Effect form. See Verify webhooks.

The rest of this page documents the Promise client until Native Effect client.

Client

createClient(config)

import { createClient } from "samva";

const samva = createClient({ apiKey: process.env.SAMVA_API_KEY! });
OptionTypeRequiredDefaultDescription
apiKeystringOne of apiKey / authTokennoneAPI key, sent as X-API-Key. The organization comes from the key.
authTokenstringOne of apiKey / authTokennoneOAuth bearer token, such as a samva login session.
baseUrlstringNohttps://api.samva.devAPI base URL. Override it for testing.
headersobjectNononeHeaders sent on every request.
fetchfunctionNoglobal fetchThe fetch implementation to use.

Pass exactly one of apiKey or authToken. With authToken, also pass the organization as headers: { "x-org-slug": "<slug>" }. See Authentication.

The Promise client accepts string API keys and does not require Effect. The Effect client accepts string | Redacted<string> and unwraps a Redacted key only for authentication.

The client sends an advisory x-samva-client header naming the SDK and its version. Override it through headers, or set it to null in a call's request options to omit it. Samva does not use it for authentication or authorization.

Calling convention

Every method takes one flat object of request parameters, path, query, and body fields together, and resolves with the decoded success value. Request options such as headers and signal go in an optional second argument. A failure throws; see Error handling.

const message = await samva.messages.get({ id: "msg_7q2xk9mvt4znw8rh" });

Each method is named for the operation it calls in the API reference: for example samva.contacts.bulkImport calls Bulk import contacts, and the reference page documents its parameters, response, and errors. samva.email.send is the one method with no operation of its own.

Namespaces

NamespaceCoversEffect moduleReference
analyticsAggregate send statistics and exportssamva/effect/analyticsAnalytics
apiKeysAPI keys, rotation, and usagesamva/effect/api-keysAPI keys
attachmentsA message's attachments and their download URLssamva/effect/attachmentsAttachments
brandsBrand themes, logos, and footers that templates importsamva/effect/brandsBrands
campaignsAudience campaigns, their runs, and recipientssamva/effect/campaignsCampaigns
contactGroupsStatic and dynamic contact groups and their memberssamva/effect/contact-groupsContact groups
contactsContact records, bulk changes, and activitysamva/effect/contactsContacts
conversationsThreads of related messages and their contactssamva/effect/conversationsConversations
customFieldsCustom contact field definitionssamva/effect/custom-fieldsContacts
emailThe send facade, domains, senders, tracking, review, and blockssamva/effect/emailEmail
extensionInstallationsInstall, enable, disable, and uninstall extensions, and read their runssamva/effect/extension-installationsMailbox extensions guide
extensionsPublish mailbox extensions and read their versionssamva/effect/extensionsMailbox extensions guide
feedbackReports to Samva about what was confusing, broken, or missingsamva/effect/feedbackSend feedback
mailboxesMailboxes, threads, messages, grants, quarantine, and eventssamva/effect/mailboxesMailboxes guides
mediaOrganization-owned uploads for attachmentssamva/effect/mediaMedia
messagesSending, listing, status, and events for messagessamva/effect/messagesMessages
namespacesSub-tenants that confine mailboxes and keyssamva/effect/namespacesMailbox namespaces guide
operationsLong-running operation status and retrysamva/effect/operationsOperations
organizationsThe organization record and its usagesamva/effect/organizationsOrganizations
scheduledMessagesFuture sends: create, list, get, cancel, and resumesamva/effect/scheduled-messagesScheduled messages
subscriptionsRequest and confirm recipient consentsamva/effect/subscriptionsDouble opt-in
templatesTemplate projects, families, workspaces, and publicationssamva/effect/templatesTemplates
unsubscribeGroupsUnsubscribe groups and their suppressed addressessamva/effect/unsubscribe-groupsUnsubscribe groups
webhooksWebhook endpoints, test deliveries, logs, retries, and secretssamva/effect/webhooksWebhooks
whoamiThe organization and credential behind the requestsamva/effect/whoamiGet the calling credential
rawEvery namespace unwrapped: result envelopes and the HTTP clientClient.rawRaw access

samva.email.send

email.send is an SDK-only facade over messages.send; both call Send a message. It fixes the channel to email, flattens the fields of the email object into its input, and accepts a single recipient or an array.

const message = await samva.email.send({
  to: "ada@example.com",
  cc: "grace@example.com",
  replyTo: "support@example.com",
  subject: "Welcome to Samva",
  html: "<h1>Welcome!</h1>",
});

console.log("Sent:", message.id);

The input takes to, cc, bcc, from, conversationId, and metadata from the message, plus every field of the email object documented on Send a message, such as subject, html, text, attachments, templateId, templateData, inReplyToMessageId, and unsubscribeGroupId.

to, cc, and bcc accept a single value or an array of any of:

FormExample
Email string"ada@example.com"
Email object{ email: "ada@example.com" }
Contact reference{ contactId: "contact_k9mvt4znw8rh7q2x" }
Contact object{ id: "contact_k9mvt4znw8rh7q2x" }, such as a contact the SDK returned

Attachments reference ready media from samva.media or carry bounded base64 content; see Send an attachment for the flow and limits.

Retry a send safely

Every email.send, messages.send, and email.addSender call sends an Idempotency-Key header. The SDK generates a fresh key per call; pass your own idempotencyKey option when your code may retry the same logical send. An identical retry returns the original message; reusing the key with a different request returns a ConflictError. See Idempotency.

const receipt = await samva.email.send(
  { to: "ada@example.com", subject: "Your receipt", text: "Thanks for your order." },
  { idempotencyKey: "receipt:order-4417" },
);

samva.messages.send

messages.send takes the message body of Send a message directly: an explicit channel, recipient arrays, and content nested under email. Use it when the send is about recipients, contacts, and conversations rather than one address.

const message = await samva.messages.send({
  to: [{ contactId: "contact_k9mvt4znw8rh7q2x" }],
  cc: [{ email: "grace@example.com" }],
  channel: "email",
  email: {
    subject: "Welcome to Samva",
    html: "<h1>Welcome!</h1>",
    replyTo: "support@example.com",
  },
});

For when to use each shape, see Email and the messages API.

Error handling

Every error the API declares becomes a class named for its _tag, exported from samva, with the error's fields as properties. All of them extend SamvaApiError. A network failure or an unreadable response throws SamvaTransportError. The Error reference lists every error and its fields.

import { RateLimitedError, SamvaApiError, SamvaTransportError } from "samva";

try {
  const message = await samva.email.send({
    to: "ada@example.com",
    subject: "Test",
    text: "Hello",
  });
  console.log(message.id);
} catch (error) {
  if (error instanceof RateLimitedError) {
    console.error(`Retry after ${error.retryAfterSeconds} seconds`);
  } else if (error instanceof SamvaApiError) {
    console.error(error._tag, error.status, error.message);
  } else if (error instanceof SamvaTransportError) {
    console.error("Network or response failure", error.cause);
  } else {
    throw error;
  }
}

Raw access

samva.raw exposes each namespace without the direct-value wrapper. A raw call returns the { data, error, request, response } envelope instead of throwing, which is useful when you need the HTTP response itself.

const result = await samva.raw.messages.get({ id: "msg_7q2xk9mvt4znw8rh" });

if (result.error) {
  console.error(result.response?.status, result.error);
} else {
  console.log(result.data);
}

Native Effect client

The samva/effect/* entrypoints form a native Effect v4 SDK. Each namespace module exports operations that return Effects directly. Install the pinned peer alongside samva:

npm install samva effect@4.0.0

Import the client capability and the modules you use, and provide the fetch-backed client Layer at the program boundary:

import { Effect } from "effect";
import * as Client from "samva/effect/client";
import * as Email from "samva/effect/email";

const program = Email.send(
  {
    to: "ada@example.com",
    subject: "Welcome to Samva",
    html: "<h1>Welcome!</h1>",
  },
  { idempotencyKey: "welcome:customer-123" },
).pipe(Effect.provide(Client.layerFetch({ apiKey: process.env.SAMVA_API_KEY! })));

const message = await Effect.runPromise(program);

Each module is the Pascal-cased namespace, imported from the path in the Namespaces table, such as * as Contacts from "samva/effect/contacts". Operations take the same flat parameter objects as the Promise client and depend on Client.Service through the Effect environment.

Errors arrive in the Effect error channel as the tagged errors from the Error reference, so Effect.catchTag("RateLimitedError", …) works on any operation. samva/effect/categories exports helpers such as isRetryable. The Effect client retries reads and sends on retryable failures by default; samva/effect/retry configures or disables that. Paginated operations add pages and items Streams. Fields annotated as absolute instants decode to Date, and secrets such as a new API key decode to Redacted.

Support matrix

SDKPackageAPI versionRuntime
TypeScriptsamvav1Node.js, Bun, and Deno (ESM)
REST APInonev1Any HTTP client

For other languages, use the REST API with your language's HTTP client.

See also

Related documentation

On this page