Sample data (recipes)
A recipe is code you deploy with the agent that creates and removes one visitor’s sample data. Nothing is copied from your real customers.
const agency = {
id: "agency", version: 1, maxRows: 40,
actions: ["invoice.read", "invoice.create", "invoice.mark-paid"],
milestones: ["invoice.created", "invoice.paid"],
seed: async (tx, resourceId) => { /* insert rows; return count */ },
cleanup: async (tx, resourceId) => { /* delete this resource */ },
};Versioning
Each recipe has an ID, a version, the actions visitors may take, the milestones you report, and a maxRows limit. Publishing freezes the current version, so edits don’t affect sessions already running. Keep old versions deployed until their sessions finish.
Seeding
Use the resourceId you’re given to create a small, related dataset and return the number of rows you created. The adapter rejects the job if that exceeds maxRows. Don’t call paid third-party APIs or use real credentials in a seed.
Cleanup
Delete every row for that resource. Cleanup must succeed even if the rows are already gone. The adapter records a tombstone so a late provisioning job can’t recreate an expired workspace.
Actions
Ledger allows reading invoices, creating them and marking them paid. Marking an invoice paid only updates sample data; no payment provider is called. Email, payments and outbound webhooks are blocked.
Personal details
Declare up to five variables on a recipe, such as { name: "company", label: "Prospect company", maxLength: 60 }. Personal links you create on the product page fill them in, and seed(tx, resourceId, variables) receives them. Seed must still work when they're absent, and only declared names, trimmed to their length, ever arrive.
See every step from the visitor’s side.
Try the Ledger example