Quickstart
Publish your first page in 5 minutes
Try it online
No installation needed. Open the Playground in your browser — edit JSON on the left, preview the rendered result on the right. Four preset templates are available: briefing, approval, dashboard, and form.
Install the SDK
Pick the SDK for your stack:
Python:
pip install surflet
# or install from local source
pip install -e ./sdk/python
TypeScript:
pnpm add @surflet/sdk
# or
npm install @surflet/sdk
Get an API Key
Create an API Key in the Surflet console. For local development, use a test key:
export SURFLET_API_KEY=sk_test_surflet123
export SURFLET_API_URL=http://localhost:3001
Test keys start with
sk_test_and point to your local dev server. Production keys start withsk_live_.
Your first page — Markdown publish
The simplest approach: pass a title and Markdown content, and publish in one line.
import surflet
client = surflet.Client(
api_key="sk_test_surflet123",
base_url="http://localhost:3001",
)
page = client.publish(
title="Customer Support Ticket Analysis #4821",
content="## Analysis\n\nCustomer reported a product quality issue. Recommend full refund.\n\n**Risk Level**: Low",
)
print(f"Page published: {page['pageUrl']}")
Open the returned URL to see the rendered page.
Structured approval page
In practice, you'll usually want richer structured content with an approval workflow:
import surflet
client = surflet.Client(
api_key="sk_test_surflet123",
base_url="http://localhost:3001",
)
page = client.publish(
title="Refund Approval #4821",
page_type="approval",
blocks=[
surflet.KeyValue("Ticket Overview", [
{"key": "Customer", "value": "Alice Wang"},
{"key": "Order ID", "value": "#ORD-20260321-7891"},
{"key": "Amount", "value": "$127.50"},
{"key": "Reason", "value": "Product arrived damaged"},
]),
surflet.Callout(
"Recommendation: Full refund. Good history, first complaint.",
style="info",
),
surflet.Table(
columns=[
{"key": "date", "label": "Date"},
{"key": "event", "label": "Event"},
{"key": "detail", "label": "Detail"},
],
rows=[
{"date": "2026-03-20", "event": "Order placed", "detail": "Standard shipping"},
{"date": "2026-03-22", "event": "Delivered", "detail": "Signed by recipient"},
{"date": "2026-03-22", "event": "Complaint", "detail": "Product casing damaged"},
],
title="Timeline",
),
],
actions=[
surflet.Action("act_approve", "Approve Refund", style="primary"),
surflet.Action("act_reject", "Reject", style="danger", requires_comment=True),
],
access=surflet.Access.authenticated(
emails=["[email protected]"],
),
on_action={
"default_url": "https://your-agent.example.com/webhook/surflet",
},
notify="slack:#cs-approvals",
)
print(f"Approval page: {page['pageUrl']}")
print(f"Page ID: {page['pageId']}")
Receive callbacks
When a user takes an action on the page (e.g., clicks "Approve"), Surflet POSTs to your configured callback URL:
# FastAPI example
from fastapi import FastAPI, Request
app = FastAPI()
@app.post("/webhook/surflet")
async def handle_surflet_callback(request: Request):
event = await request.json()
if event["event"] == "action.executed":
action = event["data"]["action_id"]
actor = event["actor"]["identity"]
if action == "act_approve":
process_refund(event["page_id"])
else:
notify_cs_agent(event["page_id"], event["data"].get("comment"))
return {"ok": True}
Publish from a template
If your use case matches a preset template, you can publish a complete structured page in one line:
page = client.publish_template("refund_approval", variables={
"customer": "Alice Wang",
"order_id": "#ORD-20260321-7891",
"amount": 127.50,
"reason": "Product arrived damaged",
"risk_score": 15,
})
print(f"Approval page: {page['pageUrl']}")
Templates automatically generate combinations of key_value, gauge, callout, and stepper blocks, with pre-configured approval chains and action buttons. 10 templates are available — see the Templates guide.
Next steps
- Core Concepts — understand Pages, Blocks, Actions, and more
- Python SDK — full Python SDK reference
- Approval Workflows — configure multi-step approval chains
- MCP Server — use Surflet directly in Claude Desktop, Cursor, and more
- Streaming Publish — progressively update page content
- API Reference — REST API endpoint documentation