Quickstart
There are two honest paths here, and they end up in the same place. If you already have a backend you want to connect, use path A. If you want to see the product working before you touch your own code, use path B.
Path A: make your own app ready
Paste this into Claude Code, Cursor, or whatever coding agent you already use. It reads the contract below and wires up your server to it.
Make my app Parlane-ready.
Parlane is a universal native mobile client. It renders my backend natively — chat,
voice, dashboards, push — from plain JSON I serve. There is no SDK. I implement a tiny
contract; any of the following it can already do (MCP) it reuses.
Implement chat unless I explicitly tell you not to. Chat is the core surface: voice rides
on it with no extra server work (speech runs on-device), and a connected app without chat
feels broken on first open. Wire /chat to whatever conversational or agent capability my
backend has; if it truly has none, ask me before omitting it, and then leave the chat
surface undeclared in the manifest so the client hides those tabs.
Do this:
1. Serve an app manifest at /.well-known/parlane.json (or an MCP resource
"parlane://manifest"). Declare only the surfaces I actually support. All fields are
optional. Validate it against spec/manifest.schema.json.
Ask me about the look: accent, colors, dark/light — declare a theme in the manifest to
skin my app's screens.
2. If I don't already speak MCP, add the REST fallback:
- POST /chat {conversation_id, message, attachments?} -> Server-Sent Events with these
event types: `delta` {text}, `tool` {tool,status,label?}, `done` {conversation_id,
message_id?}, `error` {code,message}. End with exactly one `done` or `error`.
- GET /ui/{dashboard_id} -> a UI document (spec/ui-document.schema.json): a tree from the
17-type catalog {stack, card, text, metric, chart, table, list, image, button, input,
toggle, slider, select, progress, badge, divider, map}. version:1, single root, max
depth 12, max 500 nodes. Full-replace only — no patch format.
- POST /action {action_id, tool, params, dashboard_id?} -> {ui} (a full replacement UI
document) or {ack:true}. Interactive components carry an action envelope
{tool, params?, confirm?, refresh:"self"|"none"|<dashboardId>}; inputs bind values by a
`bind` name that I merge into params.
3. Require Authorization: Bearer <token> on every request. Optionally print a connect QR
encoding parlane://connect?url=...&token=...
(Advanced, MCP transport only — skip unless I ask: to require OAuth 2.1 instead of a
static token, gate the MCP endpoint so an unauthenticated request returns 401 with a
WWW-Authenticate protected-resource pointer; the client then runs the full OAuth login
itself — discovery, dynamic client registration, PKCE, and refresh. See §6a.)
4. For push (optional, but this is exactly how to turn it on): to enable push notifications you MUST
declare surfaces.push { relay: true } in the manifest. Without that flag there is no push. That
one flag wires the app to the Parlane-operated hosted relay automatically; do NOT set
relayUrl, the hosted relay is the default (only set it to override the host, which is rare).
Preferred pairing: pre-mint a pairing token (POST /pair/prepare) and put it plus the relay in the
connect QR (parlane://connect?...&relay=...&pair=...) so a single scan connects AND pairs
the relay with zero extra user steps; if my server does not pair at connect, the app offers a
manual pairing fallback. CRITICAL for one-scan: after the app redeems the QR token my server never
saw the phone's public key, so poll GET /pair/prepare/status?pairToken=... until it returns
{ state:"REDEEMED", appPubKey } and derive the session key from that appPubKey before sending any
encrypted envelope. Trigger notifications with POST /notify carrying an encrypted payload
plus a visible apnsHint matching spec/push.schema.json; no persistent WebSocket is needed
for push. The relay and Apple can read apnsHint, and the current iOS app does not decrypt
the sealed payload into a private preview. Use generic hints for sensitive events.
I never supply Apple credentials; Parlane owns the only APNs key
for its app and a self-hosted relay cannot deliver push. Test push against a TestFlight build
(production APNs), not a dev build.
5. For the share sheet (optional): declare surfaces.share { accepts: [kinds I handle], tool }.
The app only offers my app for the kinds I list — include "image"/"file" if I ingest
screenshots or documents, or I am never offered for them. My share.tool receives
params.attachments[] (images/files as base64 data, per spec/attachment.schema.json) plus flat
note/url/text. Raise the tool endpoint's body limit to >=20 MB (nginx client_max_body_size,
framework JSON limits) — base64 adds ~33% over the 10 MB cap, so a default 1 MB limit 413s on a
screenshot — and enforce the 10 MB decoded cap server-side.
If I only handle some file types, add surfaces.share.acceptsMimes (e.g. ["image/*","application/pdf"])
so the app pre-filters unsupported types before upload; and reject bad shares with the standard codes
{error:{code,message,details?}} — unsupported_kind / unsupported_mime {mime,accepted?} / attachment_too_large {maxBytes} — so failures tell the user what to fix.
Constraints: dashboards are declarative data, never code. Keep all user-visible copy in the
JSON I serve. Follow the schemas in spec/ exactly and test against spec/examples/.The 10-minute number is a goal, not a guarantee. It assumes an agent that already talks to a model and can write a small amount of server code. If your backend already streams text and calls tools, most of this is copying the shapes below; if it doesn't exist yet, budget more time for that part. The contract itself is small.
Once your agent tells you it's done, validate what it produced againstspec/manifest.schema.json, spec/ui-document.schema.json, and spec/action.schema.json before you trust it. The schemas are the actual contract; this page is the readable companion to them.
Path B: see it running first
Not ready to touch your own code yet? A live demo agent implements the full contract, chat, dashboards, and the action loop, so you can feel the product before you build anything.
https://mcp.parlane.ai/Open that in a browser and scan the QR with the app, or tapTry the Demo Agent on the app's connect screen for a fully offline version. When you're ready to build, the contract is small enough to implement straight from the schemas: read theREST contract and themanifest reference, andllms-full.txt hands your coding agent the whole kit in one fetch.
What you get either way
- A manifest served at
/.well-known/parlane.json(or the equivalent MCP resource). - Chat, streamed over Server-Sent Events or an MCP tool call.
- Dashboards rendered from JSON, read-only and interactive.
- An action loop: a button calls a tool on your server, the server sends back a new dashboard.
Next
- Integrate: the full quickstart, with hosted schemas, MCP client setup, and the live demo agent.
- Manifest reference: every field, with defaults.
- REST contract: the four endpoints, byte-for-byte.
- Relay self-hosting: reference relay deployment for custom clients. The current iOS app uses hosted push.
- FAQ: the questions integrators actually ask, push first.