@lettrove/node
npm install @lettrove/node
Node.js 20 or newer, and edge runtimes (it uses only fetch and Web Crypto). It refuses to run in a
browser.
import { Lettrove, LettroveApiError, verifyWebhook } from '@lettrove/node';
const lettrove = new Lettrove({ secretKey: process.env.LETTROVE_SECRET_KEY! });
new Lettrove(options)
| Option | Type | Default | |
|---|---|---|---|
secretKey | string | required | lt_sk_test_… or lt_sk_live_…, from your environment. A publishable key, a cut-off key or a key with spaces is refused at once, with a message saying which. |
timeoutMs | number | 15000 | How long to wait for an answer. |
fetch | typeof fetch | the global | Your own fetch, for runtimes or tests that need one. |
lettrove.environment is 'test' or 'live', read from the key.
tokens.create(input) → { token, expiresAt }
| Input | |
|---|---|
user.id | Required. Your own id for the person (1–256 characters). |
origin | Required. The page the editor opens on: the request's Origin header. |
ttl | Optional. 60–900 seconds; default 900. |
designs.list(input) → { designs, nextCursor }
| Input | |
|---|---|
user.id | Required. |
limit | 1–200, default 50. |
cursor | nextCursor from the previous page. |
Each design: { id, name, mode, revision, createdAt, updatedAt }, newest first.
designs.get(designId, { user }) → Design
The summary fields, plus doc: the design document.
designs.export(designId, input)
| Input | |
|---|---|
user.id | Required. |
merge | { contact?, unsubscribeUrl?, preferencesUrl? } — Merge tags |
text | { links?, images?, preheader? } — how the plain text is written |
format | 'html' (default), 'pdf', 'png' or 'zip' |
fullPage | For 'png': the whole design (default) or the first screen |
With format 'html' or none, resolves with ExportedDesign: exportId, designId, revision,
mode, html, chunks, text, subject, preheader, mergeTags, rendererVersion, bytes,
warnings, design. With a file format, ExportedFile: exportId, designId, revision, mode,
format, url, expiresAt, filename, bytes, warnings, design. The types follow format.
render(input) → RenderedDesign
| Input | |
|---|---|
doc | Required. A design document you hold. |
designId | Optional. Its id: a popup's handle and a form's event carry it. |
merge, text | As for designs.export. |
The fields of ExportedDesign without exportId, designId and revision: nothing is recorded.
users.erase(userId) → void
Erases one person and everything they made. Resolves when the erasure is under way. Erasure and privacy
verifyWebhook(rawBody, signature, secret, options?) → WebhookEvent
| Argument | |
|---|---|
rawBody | The request body as a string, exactly as it arrived |
signature | The Lettrove-Signature header |
secret | The webhook's signing secret (whsec_…) |
options.toleranceSeconds | How old a delivery may be; default 300 |
Throws LettroveApiError with code signature_invalid when the signature does not match, the body was
changed, or the delivery is too old. Webhooks
LettroveApiError
| Field | |
|---|---|
code | A stable error code |
message | What happened |
status | The HTTP status, or 0 when Lettrove could not be reached (network_error) |
requestId | Quote it to support |
retryAfter | Seconds to wait, when rate_limited |
docsUrl | The code's row in Error codes, for your logs |