Quickstart
By the end of this page you’ll have a small Node app that signs nobody in, creates a document for one test user, opens it in the Proof editor, and seals it. It takes about ten minutes. Everything runs in test mode, so nothing you make here is public, and seals are marked as test seals.
You need Node 20 or later and a Proof console account.
-
Get a test key. In the console, create a platform. Call it anything; we’ll use Acme Notes, with the slug
acme. Copy its test secret key, which starts withsk_test_, and keep it on your server only.Terminal window export PROOF_SECRET_KEY=sk_test_51Hc…Test mode lets the editor load on any
localhostaddress, so you don’t need to set embed origins yet. -
Install the SDKs.
@exalto/proofis for your server;@exalto/proof-embedmounts the editor in the browser.Terminal window mkdir acme-notes && cd acme-notesnpm init -y && npm pkg set type=modulenpm install @exalto/proof @exalto/proof-embed express -
Create a user and a document. Proof has no accounts. You tell it who your users are under your own ids, and it gives each one a Proof id and stores a name to show in the editor and on seals.
setup.js import Proof from "@exalto/proof";const proof = new Proof(process.env.PROOF_SECRET_KEY);const ada = await proof.users.upsert("u_42", { name: "Ada Lovelace" }); // u_42 is your id for Adaconst doc = await proof.documents.create({ owner: ada.id, name: "Notes on the Engine" });console.log(ada.id, doc.id);Terminal window node setup.js# usr_5Kq2Lm8R doc_8Hq2Lm4RIn a real app you’d store
ada.idbeside your own user, as you would a Stripe customer id. -
Add a session route. The browser never sees your secret key. Instead, your server starts an editor session for one user and one document, and hands the page its token, which lasts 15 minutes. In a real app you’d check who is signed in first; here everyone is Ada.
server.js import express from "express";import Proof from "@exalto/proof";const proof = new Proof(process.env.PROOF_SECRET_KEY);const app = express();app.post("/proof/session", express.json(), async (req, res) => {// Your own sign-in check goes here; it would give you the user's stored Proof id.const ada = "usr_5Kq2Lm8R"; // the id setup.js printedconst session = await proof.sessions.create({ user: ada, document: req.body.document });res.json({ token: session.token });});app.use(express.static("public"));app.listen(3000); -
Mount the editor. The editor fills the element you give it and asks
getTokenfor a new token whenever the old one is about to lapse.public/index.html <!doctype html><title>Acme Notes</title><div id="editor" style="max-width: 760px; margin: 40px auto"></div><script src="https://embed.proof.exalto.ai/v1.js"></script><script>const documentId = "doc_8Hq2Lm4R"; // the id setup.js printedProof.mountEditor(document.getElementById("editor"), {document: documentId,getToken: async () => {const response = await fetch("/proof/session", {method: "POST",headers: { "Content-Type": "application/json" },body: JSON.stringify({ document: documentId }),});return (await response.json()).token;},});</script>Run
node server.jsand openhttp://localhost:3000. Write a few paragraphs. Paste a sentence from somewhere else, too. The seal in the editor’s corner fills in as you go: graphite for what you typed, grey for what you pasted. -
Seal it. Use the editor’s Seal button, or seal from your server:
seal.js import Proof from "@exalto/proof";const proof = new Proof(process.env.PROOF_SECRET_KEY);const seal = await proof.seals.create("doc_8Hq2Lm4R", { user: "usr_5Kq2Lm8R" });console.log(seal.line);// proof.exalto.ai/TQ81KD2MA · 91% typed/shaped · 0% AI · 9% external · 0 prompts · 1 session, 6minOpen
seal.url. That is what anyone you share it with sees: the seal, where the words came from, the session on a timeline, and a note that Acme Notes vouches for who Ada is.
What you built
Section titled “What you built”Your server owns who Ada is and which documents Ada may open. Proof owns the editor and the record of what happened in it. The only thing that crossed from your server to the browser was a token for one document, good for 15 minutes.
- Embed the editor properly: your own sign-in check, appearance, and events back from the editor.
- Share documents between your users, with roles and link access.
- Connect agents so your users can bring Claude Code, Codex or any MCP client.
- Read the trust model before you tell your users what a seal proves.