TypeScript-SDK

Typisierter Client für die Owlat-API, nutzbar aus Node.js, Bun, Deno oder jeder serverseitigen JavaScript-Laufzeitumgebung.

Das offizielle Paket @owlat/sdk-js stellt einen typisierten Client bereit, um aus Node.js, Bun, Deno oder jeder serverseitigen JavaScript-Laufzeitumgebung mit der Owlat-API zu arbeiten.

Installation

bun add @owlat/sdk-js
npm install @owlat/sdk-js
pnpm add @owlat/sdk-js

Schnellstart

import { Owlat } from '@owlat/sdk-js'

const owlat = new Owlat('lm_live_...')

// Send a transactional email
await owlat.transactional.send({
  email: 'recipient@example.com',
  slug: 'welcome-email',
  dataVariables: { firstName: 'Mira' }
})

Sie können auch ein Konfigurationsobjekt übergeben:

const owlat = new Owlat({
  apiKey: 'lm_live_...',
  baseUrl: 'https://your-deployment.convex.site',
  timeout: 30000,
  retry: { maxRetries: 2, initialDelayMs: 500, backoffMultiplier: 2 },
})

baseUrl ist optional und hat den Standardwert https://api.owlat.app. Sie müssen es nur für selbst gehostete Deployments setzen — richten Sie es auf die Site-URL Ihres Convex-Deployments (https://<your-deployment>.convex.site), die die API unter /api/v1/* ausliefert.

Retries und Idempotenz

Das SDK wiederholt vorübergehende Fehler automatisch — bis zu 2 Wiederholungen (insgesamt 3 Versuche) mit exponentiellem Backoff (500 ms Basis, jeweils verdoppelt). Ein 429 wird unabhängig von der Methode stets wiederholt, unter Beachtung des Retry-After-Headers. Ein 5xx oder ein Netzwerk-/Timeout-Fehler wird nur bei idempotenten Methoden (GET/PUT/DELETE) wiederholt.

POST-Sendungen — transactional.send(...) und events.send(...) — werden bei einem 5xx oder Netzwerkfehler nicht automatisch wiederholt, da der Server keinen Idempotenzschlüssel hat und eine bereits verarbeitete Sendung nicht dupliziert werden darf; diese erscheinen als Fehler, die Sie selbst behandeln. Übergeben Sie retry: false, um Wiederholungen vollständig zu deaktivieren, oder justieren Sie maxRetries / initialDelayMs / backoffMultiplier.

Ressourcen

Kontakte

Kontakte in Ihrer Zielgruppe verwalten.

// Create a contact
const contact = await owlat.contacts.create({
  email: 'mira@acme.io',
  firstName: 'Mira',
  lastName: 'Chen',
})

// Get a contact by ID
const found = await owlat.contacts.get('contact_abc123')

// Update a contact
const updated = await owlat.contacts.update('contact_abc123', {
  firstName: 'Mira',
  lastName: 'Chen-Lopez',
})

// List contacts with cursor-based pagination
const result = await owlat.contacts.list({ limit: 25 })
// result.data       — Contact[]
// result.pagination  — { limit, totalItems, cursor, isDone }

// Fetch the next page with the returned cursor
if (!result.pagination.isDone) {
  const next = await owlat.contacts.list({ cursor: result.pagination.cursor })
}

// Or iterate every contact automatically (follows cursors until isDone)
for await (const contact of owlat.contacts.listAll()) {
  console.log(contact.email)
}

// Delete a contact
await owlat.contacts.delete('contact_abc123')

Transaktional

Transaktionale E-Mails mit vorgefertigten Vorlagen versenden.

const result = await owlat.transactional.send({
  // Identify the template by slug or ID
  slug: 'order-confirmation',

  // Recipient
  email: 'buyer@example.com',

  // Data variables merged into the template
  dataVariables: {
    orderId: 'ORD-7291',
    total: '$142.00',
  },

  // Optional: override language
  language: 'de',
})
// result.status === 'queued'
// result.transactionalEmailId — id of the send record
// result.contactId, result.contactCreated, result.language

Anhänge

Sie können Dateien über Base64-kodierten Inhalt oder HTTPS-URLs anhängen (max. 10 Dateien, insgesamt 10 MB):

await owlat.transactional.send({
  email: 'buyer@example.com',
  slug: 'order-confirmation',
  attachments: [
    // Base64-encoded content
    {
      filename: 'invoice.pdf',
      content: base64String,
      contentType: 'application/pdf',
    },
    // URL (fetched server-side)
    {
      filename: 'receipt.pdf',
      url: 'https://your-api.com/receipts/ORD-7291.pdf',
    },
  ],
})

Events

Eigene Ereignisse senden, um Automationen auszulösen und Segmente aufzubauen.

await owlat.events.send({
  email: 'mira@acme.io',
  eventName: 'plan_upgraded',
  eventProperties: {
    plan: 'pro',
    mrr: 49,
  },
})

Themen

Themen-Mitgliedschaften verwalten. Die API ist reine Schreib-API (Hinzufügen/Entfernen) — es gibt keinen List-/Get-Endpunkt; kopieren Sie die topicId daher aus dem Dashboard (Themen → ein Thema).

// Add a contact to a topic
await owlat.topics.addContact({
  topicId: 'topic_abc123',
  email: 'mira@acme.io',
})

// Remove a contact from a topic
await owlat.topics.removeContact({
  topicId: 'topic_abc123',
  emailOrId: 'mira@acme.io',
})

Fehlerbehandlung

Das SDK exportiert typisierte Fehlerklassen für häufige Fehlerfälle:

import {
  Owlat,
  OwlatError,
  AuthenticationError,
  RateLimitError,
  NotFoundError,
  ValidationError,
  ConflictError,
  ForbiddenError,
  InvalidStateError,
  LimitReachedError,
} from '@owlat/sdk-js'

try {
  await owlat.transactional.send({ email: 'user@example.com', slug: 'welcome' })
} catch (error) {
  if (error instanceof ValidationError) {
    console.error('Validation failed:', error.message)
  } else if (error instanceof InvalidStateError) {
    // 422 — unverified sending domain, blocked recipient, unpublished template.
    // The most common transactional failure mode.
    console.error('Cannot send yet:', error.message)
  } else if (error instanceof ForbiddenError) {
    // 403 — suspended / abuse-blocked account.
    console.error('Not permitted:', error.message)
  } else if (error instanceof LimitReachedError) {
    console.error('Plan limit reached:', error.message)
  } else if (error instanceof RateLimitError) {
    console.error('Rate limited — retry after backoff')
  } else if (error instanceof AuthenticationError) {
    console.error('Bad API key')
  } else if (error instanceof ConflictError) {
    console.error('Contact already exists')
  } else if (error instanceof NotFoundError) {
    console.error('Resource not found')
  } else if (error instanceof OwlatError) {
    console.error('API error:', error.message, error.statusCode)
  }
}
FehlerklasseHTTP-StatusWann
AuthenticationError401Ungültiger oder fehlender API-Key
LimitReachedError402Tarif- oder Kontingentgrenze erreicht
ForbiddenError403Authentifiziert, aber nicht berechtigt (gesperrt / wegen Missbrauchs blockiert)
NotFoundError404Ressource existiert nicht
ConflictError409Doppelte Ressource (z. B. bereits vorhandene E-Mail-Adresse)
InvalidStateError422Der Zustand der Ressource blockiert die Operation (nicht verifizierte Domain, blockierter Empfänger, nicht veröffentlichte Vorlage)
RateLimitError429Zu viele Anfragen
ValidationError400Der Request-Body besteht die Validierung nicht

Typen

Alle Request- und Response-Typen werden zur Verwendung in Ihrem eigenen Code exportiert:

import type {
  Contact,
  CreateContactParams,
  UpdateContactParams,
  SendTransactionalParams,
  SendTransactionalResponse,
  TransactionalAttachment,
  SendEventParams,
  AddToTopicParams,
  PaginatedResponse,
  ApiResponse,
} from '@owlat/sdk-js'

Sie nutzen Java?

Für die JVM-Integration (Java 11+) siehe die Referenz zum Java-SDK.