SendOwl

sendowl.comcontributed by Samuele Ongaro

YES

Replaceable in one session with an AI coding agent.

Selling and delivering digital files: a buy button, a payment, and a secure download link that expires, with licence keys and drip delivery on top.

Promptfree, for everyone, and the only version there is
Build me digital product delivery that replaces SendOwl: a buy button, a payment, and a download link that cannot be passed around.

STACK
- Node 20+ with Fastify, server-rendered HTML
- SQLite through better-sqlite3, WAL mode
- One payment provider, hosted checkout, so no card data touches this
- Caddy in front

THE DATA MODEL
- products: id, slug, name, description_md, cover_path, price_cents, currency, pricing_kind, tax_category, is_active, download_limit, link_ttl_hours, licence_kind
- files: id, product_id, path, sha256, bytes, filename, position, is_active
- orders: id, customer_email, customer_name, product_id, amount_cents, currency, tax_cents, tax_country, tax_evidence_json, coupon_id, provider_ref, status, created_at, refunded_at
- download_tokens: id, order_id, file_id, token_hash, issued_at, expires_at, max_uses, use_count, revoked_at
- downloads: id, token_id, at, ip_hash, user_agent_bucket, bytes_sent, range_header, completed — append-only
- licences: id, order_id, key_hash, key_prefix, activations_max, status, issued_at, revoked_at
- activations: id, licence_id, machine_hash, at, deactivated_at
- drips: id, order_id, file_id, release_at, delivered_at
- coupons, provider_events

THE DOWNLOAD LINK, WHICH IS THE PART PEOPLE UNDERESTIMATE
- The link carries a long random token, stored hashed, tied to one order and one file
- It expires, and it has a use limit. Both configurable per product, both enforced server-side
- The file is served by the application from outside the web root, never from a guessable path and never from a signed CDN URL that outlives the token
- Range requests supported, and a resumed download counts as one use rather than five. Getting that wrong means a customer on a poor connection exhausts their limit and writes to you angry
- A part-completed download does not consume a use; only a completed one does
- Every download recorded with the address hash, so 'this link was used from forty countries in an hour' is visible
- Abuse response: throttle, then revoke, then notify — never silently break a legitimate customer's link. When you do revoke, say so and offer a fresh one on request
- Re-issue from a page the customer reaches with a link in their receipt, so a genuine failure needs no support ticket

PAYMENT AND TAX
- Hosted checkout; the order is created from the webhook, never from the browser returning to a success page
- Webhooks with signature verification, idempotency by event id, and out-of-order delivery handled
- For digital goods sold across borders the tax rate is usually the buyer's, not yours. Collect the country, apply the rate, and store two pieces of non-conflicting evidence of where they were — that evidence requirement is the part people discover a year late. Put it in the README with a note to take advice
- Refunds recorded and the download tokens revoked with them

LICENCE KEYS
- Generated per order, stored hashed with a visible prefix so support can identify one without holding it
- A verification endpoint an application can call, rate-limited, returning valid, invalid, revoked or over-limit
- Activation limits per machine hash, with a deactivation path the customer can use themselves
- Offline verification as an alternative: a signed licence file the application checks against a public key, which needs no server at all and is the better answer for many products
- Revocation on refund or chargeback, and every state change logged

DRIP DELIVERY
- Files released on a schedule from the purchase date — the second module a week later
- A worker that is idempotent, so it can run twice without sending twice
- Each release emailed with its own fresh token

THE EMAILS
- The receipt arrives immediately, with the download link, the order reference, and the tax breakdown a customer may need for their own accounts
- Deliverability matters more here than anywhere: a receipt in a spam folder is a support ticket. SPF, DKIM and DMARC on your own sending domain, documented in the README
- A resend path that needs no account, from a link in the original mail

THE STOREFRONT
- A product page and a buy button that can be embedded on any site with one snippet
- A cart if products are commonly bought together; skip it if they are not
- Fast, server-rendered, dark and light

OPERATIONS
- .env: DATABASE_PATH, STORAGE_PATH, BASE_URL, SESSION_SECRET, SMTP_URL, FROM_ADDRESS, PROVIDER_KEY, PROVIDER_WEBHOOK_SECRET, HASH_SALT
- Migrations on boot, each once
- Disk watchdog, and a bandwidth measure per product because that is the real cost of this business
- Nightly backup off the machine, restore script
- Health endpoint checking the database, mail, the provider and disk

WHAT MATTERS MOST
The download token and the range-request accounting. Build expiry, use limits and resumable serving first, then download a large file over a deliberately unreliable connection and confirm the customer is not locked out. That single case is most of the support burden in this business.

Give me the repository, migrations, .env.example, a seed product with a drip and a licence, the embed snippet, and a README with deploy steps behind Caddy, the DNS records, and the tax evidence note.

What you lose

  • Expiring, single-use download links with abuse controls, which is the part people underestimate
  • Licence key generation and validation already built
  • Payment, VAT and delivery in one purchase, with nothing to host

If you would rather not build

  • Stripe Checkout plus presigned S3 URLs
  • Lemon Squeezy, if you want VAT handled too
  • Gumroad, for the simplest possible version

What it costs

as published on their pricing page

PlanBilled monthlyBilled yearlyLast read
—$18/mo——

Their pricing page is where these came from. Seeing a different price? Tell us.

The escape hatch

open source · no votes, no paid placement

Medusa

$0

Commerce backend with digital product support through plugins.

medusajs/medusafree · open source

Vendure

$0

A commerce framework where digital delivery is a plugin you write once.

vendurehq/vendurefree · open source

Why this verdict

our own opinion · changed only by a person

82/100

Verdict yes at 82. Stripe handles payment; the interesting work is a download token that survives being posted on a forum.

History

tracked since 10 Aug 2026 · nothing is ever overwritten

Interest · last 30 dayspeak 3/day
views012330 Aug4 Sept9 Sept14 Sept19 Sept24 Sept28 Sept
— views— prompt copies none yet— votes none yet

Questions about SendOwl

answered from the record above

Is SendOwl free?

No — the plan we track is $18 a month. Starter at around $18/month billed monthly for digital product delivery.

Can you replace SendOwl by building your own?

YES. Replaceable in one session with an AI coding agent. Replacement score 82 out of 100, build time one session. Read what you lose before you decide.

How much does SendOwl cost?

$18 a month on Starter — $216 a year. Recorded 10 Aug 2026.

What do you lose by replacing SendOwl?

Expiring, single-use download links with abuse controls, which is the part people underestimate; Licence key generation and validation already built; Payment, VAT and delivery in one purchase, with nothing to host. If any of those carry weight for you, keep paying.

Is there an open-source alternative to SendOwl?

Yes: Medusa, Vendure. The prompt on this page is for when you want it your way instead.

Related entries

same category first, most replaced first

All 27 in Commerce & contracts

Not sending yet

Every week, something stops being worth paying for.

New verdicts, prices that moved, entries added. One email a week. Unsubscribe in one click. Nothing is being sent yet — your address is kept here, and the first issue is the first thing it is used for.

free forever · no tracking pixel · stored here, never passed to anyone

Esc