Documentation
sendapage turns a brand template + a one-off brief into a personalized microsite at sendapage.com/p/<slug>. This guide covers the full surface — templates, briefs, pages, analytics, and the API.
Quickstart
Three steps from zero to a published page:
- Sign in at /login with GitHub or Google. You start on the Free plan with 5 lifetime pages.
- Get a template. Easiest path: clone a starter on /templates (post-meeting follow-up, sales pitch, recruiting offer, investor update, wedding invite). Or chat with the AI to draft one at /templates/author. Or write one by hand at /templates/new.
- Generate a page at /pages/new: pick the template, drop in a brief, hit Generate. The microsite ships in ~60 seconds.
Send the link. Watch engagement land in the dashboard the moment the recipient opens it.
Templates
A template is the AI's brand handbook. It's reused across every page generated from it, so put effort into one good template — not into editing the AI's output afterwards.
Three ways to create a template
- Clone a starter — fastest. Five proven templates on /templates: post-meeting follow-up, sales pitch / deal room, recruiting offer, per-LP investor update, and a consumer wedding invitation. One click clones into your workspace; edit afterwards however you like.
- Author with AI — interview-style chat at /templates/author. The AI asks about your brand, voice, audience, and CTA, then drafts the template for you. Live preview shows the draft as it builds; one click saves.
- Manual — start from a blank textarea at /templates/new. Most expressive, most work.
What goes in the instructions field
Treat it like onboarding a designer. Cover:
- Brand voice — formal, playful, technical, etc.
- Visual direction — colours, typography, layout density.
- Required sections — e.g. hero, value props, social proof, CTA.
- What NOT to include — e.g. no testimonials unless provided in the brief.
- The CTA — what action you want the recipient to take.
- Tailoring rules — for example, "if the recipient is a manager, lead with team-level outcomes; if an IC, lead with day-to-day workflow."
Analytics markup (data-track-section, data-cta="primary") is enforced globally — you don't need to mention it in templates.
Attaching template files
Upload files when creating or editing a template:
- Markdown / text / JSON / YAMLfiles drop into the agent's working directory next to the instructions — useful for canonical brand info, FAQs, structured product data, sample copy.
- Images, fonts, and other binary assets are placed in
./assets/<filename>and the agent will reference them directly in the generated HTML. URLs are rewritten at serve time so links work for the recipient.
Per-template caps: 20 files, 10 MB each. Images, SVG, fonts, PDF, markdown, JSON, YAML, plain text are all accepted.
Briefs
A brief is the case-specific input — who you're sending the page to and why. The agent personalizes the template using only what's in the brief plus any uploaded files. It won't invent dates, prices, names, or quotes.
Recommended structure
Recipient: Jane Smith, VP Procurement at Globex
Stage: Stage 3 (proposal review)
Key context:
- Renewal date 2026-09-15
- Current annual spend with us: $124k
- Previously raised concerns about onboarding ramp time
- Scoped expansion into APAC offices
Goals:
- Reaffirm the renewal value
- Pre-empt the ramp-time objection
- Open the APAC expansion conversationThe brief is a free-text field — markdown works, but plain prose is fine too. The clearer and more specific you are, the better the page.
One template, many briefs
One template + many briefs is the pattern. If you find yourself editing the template per recipient, you're fighting the system — move the variability into the brief.
CTAs & context
Two structured fields supplement the free-text brief.
CTAs (per-page)
Add labelled URLs the agent can pick from when emitting CTA anchors. The template decides which label to use for which audience; you supply the destinations.
{
"ctas": [
{ "label": "book", "url": "https://calendly.com/yourname/30min" },
{ "label": "video", "url": "https://www.loom.com/share/abc123" }
]
}Set in the dashboard form on /pages/new, or pass context.ctas on the API.
Free-form context
Anything else structured (CRM payload, deal data, computed fields) goes in context as JSON. The agent sees it in context.json alongside the brief and uses it where the template tells it to.
Page features
Tags
Free-text labels for organisation. Filter pages on the list view by tag chips. Set on create (comma-separated) or via API.
Password protection
For confidential sales rooms / NDA-required pages. Set a password on the page detail (Settings → Password protection). Recipients see a password gate at /p/<slug> until they enter the password; their unlock is remembered for 4 hours via an HttpOnly cookie scoped to that slug.
Duplicate
On a ready page, "Duplicate" copies brief + template + context + tags and fires a fresh generation. Useful for trying a variant without editing the original.
Expiry
Pages don't expire by default. Set expiresAt on a page (via API) to time-limit access — after the deadline, /p/<slug> returns 410. Useful for stage-gated sales rooms.
Open Graph / share previews
Every page auto-generates an OG card image (clean black-on-white with the page title). Pasting /p/<slug> into Slack, iMessage, LinkedIn, X, or Gmail unfurls a proper preview without any setup.
Watermark
Free-tier pages display a small "Made with sendapage" mark in the corner. Paid tiers serve unbranded.
CSV import
For batch follow-ups (post-conference lists, CRM exports), drop a CSV at /pages/import. Each row becomes a page.
- No column mapping — the entire row is sent to the agent as JSON. Your template's instructions decide which fields matter.
- Optional "shared context" box — text applied to every row (sender, sign-off, default CTA, conference name, etc.).
- Caps: 200 rows / 2 MB per import. Each row is quota-checked atomically.
- Slug auto-derived from a name- or email-shaped column when present.
Analytics
Every published page ships with first-party tracking. No third-party cookies; visitor identifiers are page-scoped and rotate daily so visitors aren't trackable across different pages.
What we capture
- Views — server-rendered, captured even if JavaScript is blocked.
- Active time on page — only counts seconds the tab is visible & focused.
- Scroll depth — milestones at 25/50/75/100%.
- Section dwell — how long the visitor spent looking at each
data-track-section. - Link & CTA clicks — anchors with
data-cta="..."are bucketed as conversions. - Geo & org — country / city from the request, plus reverse-DNS to org name when available.
- Engagement score (0–100) per session, derived from active time + scroll + CTA clicks + section breadth.
- Live indicator — pulsing badge when someone is actively on the page right now.
First-view alerts
Configure Slack / email / webhook alerts that fire when a recipient opens the page, optionally only for visitors from specific company domains (org match).
Where to find it
On the page detail in the dashboard. Per-section heatmap, geography breakdown, sortable visitor table, and a real-time activity feed.
API reference
Use the API to manage templates, generate pages, and read status from any backend (CRM, ATS, automation tooling). API access is included on Growth and above.
Authentication
Create a key at /api-keys. Pass it in the Authorization header.
Authorization: Bearer sap_live_xxxxxxxxxxxxxxxxxxxxTemplates
Full CRUD. Asset URLs you supply are server-side fetched into our blob storage (so the agent can read them at generation time) — must be public HTTPS.
# Create
curl -X POST https://sendapage.com/api/v1/templates \
-H "Authorization: Bearer $SAP_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "OutboundCon 2026 — booth follow-up",
"description": "Personalized post-booth follow-up.",
"instructions": "# Brand voice\n...",
"asset_urls": [
{ "url": "https://example.com/logo.svg", "name": "logo.svg" }
]
}'
# List
curl https://sendapage.com/api/v1/templates -H "Authorization: Bearer $SAP_KEY"
# Get / update / delete
curl https://sendapage.com/api/v1/templates/$TEMPLATE_ID -H "Authorization: Bearer $SAP_KEY"
curl -X PATCH https://sendapage.com/api/v1/templates/$TEMPLATE_ID \
-H "Authorization: Bearer $SAP_KEY" -H "Content-Type: application/json" \
-d '{ "instructions": "# Updated voice\n..." }'
curl -X DELETE https://sendapage.com/api/v1/templates/$TEMPLATE_ID -H "Authorization: Bearer $SAP_KEY"Pages
Create / list / get / delete. Page creation returns immediately with status queued; generation runs in the background.
# Create
curl -X POST https://sendapage.com/api/v1/pages \
-H "Authorization: Bearer $SAP_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "31058a46-73bf-4488-a52a-728b73465e09",
"brief": "Recipient: Jane Smith @ Globex...",
"context": {
"deal_id": "OPP-1234",
"ctas": [{ "label": "book", "url": "https://calendly.com/me/30min" }]
},
"slug_hint": "globex-q1",
"webhook_url": "https://your-app.com/sendapage-callback"
}'
# Poll / list / delete
curl https://sendapage.com/api/v1/pages/$PAGE_ID -H "Authorization: Bearer $SAP_KEY"
curl https://sendapage.com/api/v1/pages -H "Authorization: Bearer $SAP_KEY"
curl -X DELETE https://sendapage.com/api/v1/pages/$PAGE_ID -H "Authorization: Bearer $SAP_KEY"Page response shape
{
"id": "8e2a...",
"slug": "globex-q1-9td4hk7hrt",
"status": "ready",
"title": "Renewal review for Globex",
"url": "https://sendapage.com/p/globex-q1-9td4hk7hrt",
"created_at": "2026-05-03T07:38:49.000Z",
"published_at": "2026-05-03T07:39:42.000Z",
"error": null
}Statuses: queued → generating → ready (or failed with error populated).
Errors
401 invalid_api_key— bad / revoked key402 api_access_not_included— upgrade to Growth or higher402 quota_exceeded— monthly page limit hit402 template_limit_reached— plan's template count maxed404 template_not_found/404 not_found413 asset_too_large— over 10 MB422 asset_fetch_failed/422 asset_mime_not_allowed400 invalid_payload— malformed body; details indetails
Webhooks
Pass a webhook_url on page creation. We POST a JSON payload when generation finishes (success or failure):
{
"event": "page.completed",
"page": {
"id": "8e2a...",
"slug": "globex-q1-9td4hk7hrt",
"status": "ready",
"url": "https://sendapage.com/p/globex-q1-9td4hk7hrt",
"title": "Renewal review for Globex",
"created_at": "...",
"published_at": "...",
"error": null
}
}We post once. Build the receiving endpoint to be idempotent on page.id. URLs are validated server-side: HTTPS only; private/loopback/cloud-metadata addresses are rejected up-front.
Integrations
Google Forms / Typeform / any form tool
Wire a form to auto-generate a sendapage on submission via Apps Script:
const SAP_API_KEY = 'sap_live_...';
const SAP_TEMPLATE_ID = 'your-template-uuid';
function onFormSubmit(e) {
const v = e.namedValues || {};
const f = (k) => (v[k] && v[k][0]) || '';
const name = f('Full Name') || f('Name');
const email = f('Email');
if (!name || !email) return;
const brief = ['Recipient: ' + name, 'Email: ' + email,
'', 'Notes:', f('What did you want to chat about?') || ''].join('\n');
const res = UrlFetchApp.fetch('https://sendapage.com/api/v1/pages', {
method: 'post',
contentType: 'application/json',
headers: { Authorization: 'Bearer ' + SAP_API_KEY },
payload: JSON.stringify({
template_id: SAP_TEMPLATE_ID, brief,
context: { recipient: { name, email } },
}),
});
// Optionally write back the URL into the linked Sheet from JSON.parse(res.getContentText()).url
}CRM stage triggers
Most CRMs (HubSpot Workflows, Salesforce Flow, Pipedrive automations) can fire a webhook when a deal advances. Point that webhook at POST /api/v1/pageswith the deal's rep + prospect data as the brief, and use webhook_url to feed the generated URL back into the deal as a custom property.
Pricing & quotas
See the pricing table on the landing page for current tiers. Highlights:
- Free — 5 lifetime pages, watermark, 1 template
- Starter $39/mo — 50 pages/mo, 3 templates
- Growth $79/mo — 250 pages/mo, 10 templates, custom domain, API access
- Scale $149/mo — 1,000 pages/mo, unlimited templates, engagement alerts
- Enterprise — SSO, audit logs, custom volume — talk to sales
Manage your subscription at /billing.
FAQ
How long does generation take?
Typically 30–90 seconds. Templates that ask the agent to do brand research take longer.
Which AI model is used?
sendapage runs Claude Code in a sandbox against an Anthropic-compatible endpoint. The model is set workspace-wide and tuned by the operator — there's no per-template or per-user model picker. We've picked a model that hits the right quality/cost tradeoff for personalized HTML; we change it as the frontier moves.
Can I edit the generated HTML?
Not yet — pages are immutable artifacts. If the output isn't what you wanted, refine the template or brief and regenerate (the "Duplicate" button on a page makes this a one-click loop). Post-edit support is planned.
Can I use my own domain?
Custom domains land at Growth and above. Configure under /billing.
Do generated pages expire?
Not by default. Set expiresAt per page via the API to time-limit a link. After the deadline, the public URL returns 410 Gone.
Can I require a password to view a page?
Yes. On the page detail, Settings → Password protection. Visitors see a password form before the page; an unlock cookie remembers them for 4 hours.
Is the data private?
Briefs, templates, and generated pages are visible only to your account. Visitor analytics use a daily-rotating salted hash, scoped per-page — visitors aren't identifiable across different pages and cannot be re-identified after the daily rotation.
Something missing? Email hello@sendapage.com.