Postlane

Help & guides

Set up a project, write an email, and connect the actions in your app to the right messages.

Building an integration? Open the API documentation for endpoints and examples, or download the OpenAPI specification.

Get started without sending email

  1. Select your app in the project switcher, or have an administrator create a project.
  2. Open Brand & components → Edit project brand to set your brand, header logo and footer.
  3. Open an Email library draft, edit its content and inspect both HTML and text previews.
  4. For onboarding, open Workflows → New signup guide. Review the paused example, then use Save & simulate.
  5. For a newsletter, create one issue and schedule it for a specific date. A scheduled issue does not repeat automatically.

New installations default to dry-run. Choose Delivery mode in Administration → Global mail settings, or override it in Project & integration. Live SMTP enables real delivery when sender/relay settings and the installation guard are ready. A dry-run renders and logs a message without contacting SMTP, and that job cannot become a live send later. Live sending must be enabled separately by the installation operator.

Your project dashboard

The home screen shows all-time totals for the selected project. Switch projects to see that app's counts, or use Refresh for current data. Counts come from the full database history, not just the latest messages shown in the delivery log.

Messages processed includes sent, dry-run, failed, unknown and skipped messages. Messages sent means accepted by the SMTP relay, which does not confirm inbox delivery. Queued includes retries and messages currently sending. Needs review includes failed, unknown and held messages. These cards overlap; they are not separate parts of a total.

The purpose table separates newsletters, onboarding, app notifications, opt-in confirmations and tests. Totals count messages, not retry attempts. The workflow/issue list shows the eight largest sources; the events list shows signup and other events received from your app. Events can create several messages or none. Use the Delivery log, Workflows and Reports links to inspect the underlying activity.

Lists and focused editors

Audience, reusable components, API keys and accounts open with their records or overview first. Choose Add, New, Create or Edit to open a dedicated editor. Use Cancel or Back to leave without saving staged changes. Saving a subscriber, audience or account returns to its list; branding and mail settings stay open after saving for further review.

Project & integration → Edit project settings opens sender and relay configuration. Create API key opens a separate permissions form. Delivery log → Feedback settings opens relay log configuration. Preferences → Add passkey opens its own credential form. Forms use multiple columns where space allows and stack on mobile.

SMTP security and Mailpit testing

Both global mail settings and project relay overrides have an SMTP connection security dropdown. Automatic uses TLS on port 465 and requires STARTTLS on other ports. Explicit TLS and STARTTLS options also support nonstandard ports.

For the internal Mailpit capture server use mailpit.mailpit.svc.cluster.local, port 1025, and Plain SMTP, normally with no username/password. Plain SMTP disables TLS. Choose SMTP delivery mode to transmit into Mailpit; Dry-run does not contact it. Use encrypted modes for external delivery relays.

ETLS 502 STARTTLS means the server rejected Postlane's required TLS upgrade before message submission. After fixing the security setting, queue a new test; failed deliveries are not resent automatically.

Private image storage

Administrators manage the shared private bucket in Administration → Image storage. Test connection verifies write/read/delete access without sending email. Save settings encrypts the access credentials; blank credential fields keep the stored values.

This installation requires S3. Logos and email images stay in the private RustFS bucket, with metadata in Postgres. Email recipients receive embedded images and never access the bucket. There is no automatic fallback if storage is unavailable.

Move existing images to S3 copies legacy database images, checks each uploaded object's size and checksum, then removes the database bytes. Existing template references stay valid; interrupted migrations can be repeated. The bucket location is fixed after configuration; credentials can be rotated. Back up both the database and bucket.

Projects and mail settings

Use one project per app. Each project has its own contacts, opt-outs, templates, brand, newsletters, workflows and API keys. The same email address can have different preferences in different projects.

Project & integration holds that app's URL, From/Reply-To addresses, postal address, relay override and scoped API keys. Keys are shown once; store them in your app's server-side secrets. Revoke and replace a key if needed.

Administrators manage the shared relay under Administration → Global mail settings. Projects inherit it by default. A project override uses its own complete SMTP profile; credentials are not mixed between profiles. Blank sender fields inherit their global defaults, so review the From address for each app. Reply-To is where human replies go; Postlane does not log into that mailbox to send messages.

SMTP delivery uses your existing relay. Postlane is not a mail server. Host, port and SMTP credentials come from the relay provider; they are separate from a recipient's mailbox login. A valid sender is required for normal live delivery. The postal address is optional; leave it blank to omit it from the footer. Saving relay settings never itself sends a message.

For U.S. marketing messages, include a valid physical postal address. Purely transactional account notices are generally exempt from that requirement. Classification depends on the actual content, not the template label. See the FTC CAN-SPAM guide.

Message width and body images

In Brand & components → Edit project brand → Message width, choose Centered (560 px content width) or Full client width. Full width fills the client's available reading area, with a 12 px background margin. This setting belongs to the selected project.

Each body image can fill the available email width or use a 16–1600 px maximum. Images keep their aspect ratio and shrink on smaller screens. New uploads default to full width. The header logo has its own width setting. Changes apply to new messages; existing queued messages retain their saved layout.

One email composer: Styled, Plain and Code

Styled edits the complete body on one canvas, with the project header and footer around it. Use the shared toolbar to format text and insert images, buttons, links, dividers or reusable components. Click an image or link to edit it. Plain previews the generated text version. Code edits the same body as HTML with allowed inline styles.

Marketing versus Transactional is a separate Email purpose setting. Both can use Styled/HTML or MJML. The transactional Published control makes a saved template available to the transactional API. Save & queue test first saves your current draft, then asks for a test recipient.

Optional MJML is selected in Code format. Import a single .mjml file or type source. It compiles locally on save/preview; Styled and Plain become previews for that format. Use Upload image to insert an embedded CID reference. Includes, raw elements, custom fonts, scripts, remote image URLs and ZIP imports are not supported. Code errors are shown without replacing saved content.

HTML and MJML use Postlane variables such as {{name}} and {{data.field}}. Shared branding and marketing unsubscribe are added by Postlane. Editing an existing body converts it to sanitized HTML; opening and saving without a body edit preserves its original structure. Reusable components remain shared references in visual/HTML templates; MJML conversion copies their content.

Write an email and apply your brand

In Email library, open a draft or create a template. Give it an internal name and a recipient-facing subject. Add headings, rich text, buttons, dividers, images and reusable components. Rich text supports formatting and safe HTTPS links. Use the HTML/text preview tabs to check the result before saving.

Personalization

Use {{name}} for a contact's name and {{properties.plan}} for a custom contact property. Transactional templates can also use {{data.orderNumber}}. Administrator previews use synthetic sample data; they do not establish that your app supplied every transactional field.

Logos and images

In Brand & components → Edit project brand → Email header logo, upload a PNG, JPEG or WebP, set its description, size, optional HTTPS link, background and alignment, then save the brand. A light transparent wordmark needs a dark background. Removing the logo restores the text brand header.

For content images, use the composer toolbar’s Image button or paste/drop an image file. Uploads are limited to 5 MB and 16 megapixels. SVG, GIF and animation are not accepted. Images are embedded in outgoing emails, so recipients do not need access to Postlane or Tailscale. Clients can still choose to hide images; supply useful descriptions.

Reusable components are shared inside a project. Editing one affects future previews and newly queued messages. Already scheduled messages and existing workflow enrollments retain their saved content, branding and image references.

Test a template

Queue test email uses the saved template and the recipient you explicitly enter. In dry-run it creates a rendered log only. In live mode, you must acknowledge an actual send. Test sends never grant marketing consent, and suppression still blocks delivery.

Audience, consent and preferences

Audience shows each project's contacts, categories and restrictions. Open a contact's history to see incoming events, recorded consent, workflow decisions and delivery attempts. An account signup or verified account email is not automatically marketing permission.

  • Consent: record permission and its source. Your app should send consent: true only when the user actually opted in.
  • Newsletter: allows newsletter broadcasts when marketing consent is present.
  • Onboarding: allows the current workflow email system when marketing consent is present.
  • Unsubscribe: stops marketing across this project, including newsletters and onboarding. Later app updates cannot silently undo it.
  • Suppression: blocks all delivery, including transactional and test emails. Use it for addresses that must not receive mail.

Marketing emails include a project-scoped preferences/unsubscribe link. A recipient can choose categories or unsubscribe. Opening the preferences page is read-only; changes require submission. Opt-outs in one project do not automatically change another project's preferences.

Optional double opt-in

In Audience tools, enable double opt-in if you want new app/import consent confirmed by email. Requested categories remain pending until the user confirms. Confirmation links expire after 24 hours; opening the link alone does not confirm. Existing consent is retained. For a pending signup, the workflow's delay starts after confirmation. In dry-run, the confirmation email is logged rather than sent; its administrator preview exposes a confirmation-page link for testing.

Import, export and segments

Audience tools previews CSV validation before import. Imports support up to 500 rows/120 KB and require a permission acknowledgement; consent: true needs a consent source. Imports can preserve/set unsubscribe and suppression but cannot clear them. Export includes these restrictions and neutralizes spreadsheet formulas. Export is capped at 10,000 contacts.

Segments saves all/any rules over contact fields and custom properties. Selecting a segment copies its rules into a newsletter/workflow; editing the segment later does not silently change those copies. An import records an import event, rather than pretending to be a signup.

Compose and schedule a newsletter

  1. Write and save the email template in Email library.
  2. Open Newsletters and create a new issue.
  3. Choose the template and audience, then save the issue draft.
  4. Choose a date/time in your computer's local time zone and select Save & schedule this issue.
  5. Review outcomes in Delivery log.

Scheduling freezes the issue's current content and opted-in audience. Consent, suppression, newsletter preference and audience rules are checked again before delivery. A scheduled issue is immutable; compose another issue for next month or changed content. It never automatically resends each month. You can cancel queued deliveries; a submission already in progress may finish.

Workflow triggers, timers and paths

The current trigger is a custom event received from your app. The Trigger event field is its exact name, such as signup. Creating a workflow does not connect your app automatically or watch its signup page. Your backend must send the matching event to the project's Events API.

Select a card on the workflow canvas to open its settings panel. The trigger card contains the event, audience, frequency and exit rules. Email, wait, filter and branch cards each have their own settings. Use Settings to rename the workflow. Done closes the panel; Save workflow saves all your changes.

Use the + between cards to insert a step, then choose its type in the panel. Use the move and remove controls in that panel to rearrange the path. Explicit destinations keep pointing to the same step when possible; removing a destination or moving it before its source changes that path to Exit. Review paths before saving.

  1. Select the trigger card to set an event name and entry audience.
  2. Add email, delay and branch steps. Timers support Immediately, Minutes, Hours and Days.
  3. Choose whether a paid upgrade or onboarding completion should stop the sequence.
  4. Save and simulate with synthetic contact data. You can simulate a later upgrade/completion and inspect the route without creating contacts or sending email.
  5. Save your draft, then open the Paused status menu and choose Resume workflow when ready to accept events. This takes effect immediately and does not enable SMTP.

Use the status menu in the workflow list or editor to pause, resume, or archive. Saving content preserves that status. Status changes are immediate and do not save unfinished content edits. Pause holds new enrollments and queued workflow sends; a send in progress may finish. Resume continues existing enrollments when due; it does not replay events received while paused. Archive also pauses the workflow and moves it into the Archived view, preserving history and contacts. Restore returns it as paused; resume is a separate action.

Choose Once per contact or Each distinct event as the trigger frequency. Repeated requests with the same event ID never enroll again. Event names are case-sensitive and must match exactly. Use up to 80 letters, numbers, underscores or hyphens (for example, map a provider’s invoice.paid to invoice_paid). Entry for marketing workflows requires consent, the onboarding preference, the audience match and no unsubscribe/suppression. Transactional account-notice workflows require published transactional templates and a key with both events and transactional scopes. They respect suppression and audience rules, but do not require marketing consent. Recipient, name and properties are frozen from the event. Existing contacts/events are not automatically replayed when you activate a workflow.

A branch evaluates the contact's current fields and follows its Yes or No destination. Destinations must point forward or finish the path; cycles are not supported. The diagram lets you select steps and shows recorded path arrivals, not inbox deliveries.

Existing enrollments keep their saved steps and content. Pausing stops queued workflow deliveries; timers keep their original deadlines, so eligible overdue steps can run when resumed. Save & simulate saves the draft first; the simulation itself writes no contacts/jobs and assumes successful delivery and worker availability.

There are no native Stripe/Clerk/Supabase trigger adapters, automatic contact-change trigger selectors or “every event” workflow re-entry yet. Your app can send named custom events with updated contact properties. Scheduled newsletters are a separate compose-and-schedule feature.

Connect your app

Have an administrator create an events-scoped key in Project & integration. Your backend calls POST /api/events with Authorization: Bearer YOUR_PROJECT_KEY. The key selects the project; do not put it in client-side JavaScript. A provider webhook adapter must verify and translate its provider's payload into this format.

This example assumes the user actually selected the getting-started email checkbox:

{
  "id": "signup_user123_v1",
  "name": "signup",
  "contact": {
    "externalId": "user123",
    "email": "[email protected]",
    "name": "Alex",
    "consent": true,
    "consentSource": "Getting-started checkbox selected at signup",
    "onboarding": true,
    "paid": false
  }
}

Use a unique stable event ID per occurrence and retry failures with the same ID and exact payload. Do not generate a new ID for every network retry. Existing event IDs with changed payloads return 409. A 200 response records the event; it does not mean a workflow matched or an email was delivered.

Supply externalId consistently for account changes so email-address changes retain the same contact and opt-outs. Update paid/completed fields when those states change. Omit consent unless it genuinely changed; omitted preferences are not treated as opt-in. Scalar custom properties are supported, and null removes a property.

Open the API reference for all fields, authentication scopes, examples and error responses. Download OpenAPI JSON or YAML for API clients and tooling. The integration contract includes events, transactional email and health; browser-only administrator endpoints are not a public integration API.

Send an essential account message

For receipts and other essential account messages, create a template with purpose Transactional and mark it Published. Create a key with the transactional scope, then call POST /api/transactional with a stable request ID, the published template ID, recipient and required data.

Use {{data.fieldName}} in text/subject. A button destination may be exactly {{data.receiptUrl}}; its resolved value must be an absolute HTTPS URL. Missing data and unsafe links reject before queueing. The request snapshots the saved template and data. Repeating an identical ID/payload returns the existing job; changed input under that ID returns 409.

Transactional messages do not grant marketing consent or start a workflow, and they omit marketing unsubscribe controls. Suppression still blocks them. Use newsletters/workflows for optional marketing. “Queued” or “SMTP mode” is not a promise of delivery; use the Delivery log for actual outcomes.

Read the Delivery log

  • Queued: waiting for its due time and worker.
  • Dry-run: rendered successfully without contacting SMTP.
  • Sent: the SMTP relay accepted the message. This does not confirm delivery to the destination server or inbox.
  • Relay: delivered: a matched provider report confirms destination-server acceptance, not inbox placement or that someone read it.
  • Skipped: a preference, consent, suppression, audience or workflow exit check prevented delivery.
  • Failed: inspect the attempt/result for a rendering or delivery failure.
  • Unknown: a timeout/disconnect or worker interruption left the SMTP outcome uncertain. Check provider logs before retrying; an automatic resend could duplicate a message.

Use Preview for the exact frozen HTML/text and Details for attempts. Resolving an unknown outcome records your conclusion; it does not resend the email. Reports summarize recorded operational states without open/click/conversion attribution.

Paging and clearing delivery logs

The delivery log pages through the full retained history, with 25, 50 or 100 entries per page. Administrators can delete one completed entry, select up to 200 across pages, or use Delete all completed logs for the selected project. Deletion requires confirmation; deleting all also requires typing DELETE ALL.

Queued, sending, held and unknown outcomes are protected. Resolve an unknown SMTP outcome against provider records first. Deleting a log removes that job's email snapshot, attempt details and relay records, and stops future relay checks for it. It does not cancel a delivery, unsubscribe anyone, or resend a message.

Small delivery receipts remain so duplicate API calls and workflow processing cannot recreate the email. Lifetime sent/processed totals are preserved; dashboard Needs review excludes cleared failures. Subscriber profiles, consent evidence, workflow history and workflow enrollment snapshots remain separate. Provider logs, exported SigNoz telemetry and backups are not deleted by this action. Keep log details while you still need them for troubleshooting; cleared details cannot be restored from Postlane.

DuoCircle feedback

Administrators can use Check API connection without sending email. Choose the correct provider region. The check uses the saved global/project relay credentials. Matching delivery records requires an actual Postlane SMTP submission and an exact recipient plus relay transaction ID or message header ID. Matching only by subject or domain is insufficient.

Automatic polling is optional. Confirmed invalid-recipient suppression is a separate option and should only be enabled after validating a controlled failure. Policy/authentication errors must not suppress valid subscribers. Provider API access and successful-message matching do not prove bounce classification or inbox placement. No inbound support-mailbox login is needed for log polling.

Preferences and administration

Click your profile row at the bottom of the sidebar to open Preferences → Account security. You can change your password, enroll an authenticator, save/regenerate recovery codes and add/remove passkeys. Authenticator setup is active only after you verify a code. Password sign-in then requires TOTP or a recovery code; passkeys are a separate sign-in method with device verification.

Recovery codes work once. Save them privately before leaving setup. Passkeys are tied to the installation hostname; an alternate hostname/IP is not interchangeable. Sign out with the separate icon next to your profile. Password changes sign out other sessions.

Administration is restricted to Admin accounts and has a side menu for Accounts & access and Global mail settings. Account changes require the acting administrator's password. Role/profile/password changes and disabling invalidate the target's sessions. Account deletion requires typing its username. The original administrator is protected from administrative deletion, disabling, demotion and password reset; it changes its password through its own Preferences.

User accounts can work with email content, contacts, newsletters and workflows across projects. Only administrators manage accounts, projects, API keys and relay configuration. Human accounts currently share project access; there are no per-project memberships. Public signup and email invitations/password resets are not provided.

Common questions

Why didn't the workflow start?

Check that your app actually sent the event, that its name exactly matches the trigger, and that the workflow is active. Check the contact's audience match, consent, onboarding category, pending confirmation and restrictions. A contact that already entered this workflow cannot enter it again. See the contact's history. Simply adding a contact or activating a workflow does not recreate a past signup event.

Why isn't email being delivered?

A dry-run is expected to send nothing. Select Live SMTP globally or per project; existing dry-run jobs are never resent. For normal SMTP delivery, the installation operator must enable the guard and configure a valid relay and From address. The postal address is optional. Both the web app and worker are required for scheduling/delivery. Check the job result and provider logs rather than repeatedly submitting new send IDs.

Why didn't a template change update a scheduled email?

Scheduled issues and enrolled workflows retain their frozen content. Create another newsletter issue for the changed version. Draft previews and future enrollments use newly saved content.

Why does saving return a conflict?

Another tab/user changed the same draft/settings, or an API request ID was reused with different input. Reload the current version before saving edits; retry API requests with their original ID/payload.

Why can't I see Administration?

Your account needs the Admin role. Ask an existing administrator to review your role; navigation hiding does not replace the server's authorization checks.