BUILT FOR YOUR CODEBASE
Your templates.
Your types.
Your delivery stack.
Keep presentation in Papier and application logic in your app. Bring them together with a generated TypeScript client.
Create your workspaceSET UP ONCE
Connect your project.
Create an email template in your workspace, give it a data schema, and publish it. Then install the SDK and connect your local project.
npm install @usepapier/client @usepapier/cli
npx @usepapier/cli login
npx @usepapier/cli init
npx @usepapier/cli syncAuthenticate in your browser.
Select your organization and projects.
Resolve versions and generate types.
A SMALL INTEGRATION
Render with real data.
The generated createPapier factory knows your projects, template names, and data shapes. Render HTML, then pass it to your existing delivery provider.
Example: a project named acme and a published welcome-email template with a name string in its schema. Replace these with your own.
import { createPapier } from '@usepapier/client';
const papier = createPapier({
project: 'acme',
apiKey: process.env.PAPIER_API_KEY,
environment: 'production',
});
const html = await papier.emails.welcomeEmail.renderHTML({
data: { name: 'Alex' },
});
// Send the rendered HTML with your existing email provider.
await yourEmailProvider.send({
to: 'alex@example.com',
subject: 'Welcome aboard, Alex',
html,
});Your provider stays yours. Rendering needs no email adapter. To use the SDK’s send() methods, configure an email adapter in emailConfig.adapters.
Working with an outbox?
Use build() to validate and create a serializable payload for later sending. It returns the template reference, recipient, and data; use renderHTML() when you need the rendered HTML.
// Validate now. Store the payload for later.
const payload = await papier.emails.welcomeEmail.build({
to: 'alex@example.com',
data: { name: 'Alex' },
});
await yourOutbox.insert(payload);
// In a worker, with an email adapter configured:
// await papier.send(payload);yourEmailProvider and yourOutbox represent your own application services.
CHANGE WITH INTENTION
Keep versions explicit.
Choose a template version range in .papier/papier.json. Sync to resolve versions, update the lockfile, and regenerate your client.
{
"organization": "your-team",
"projects": {
"acme": {
"templates": {
"welcome-email": "^1.0.0"
}
}
}
}Sync when templates change
Run npx @usepapier/cli sync to fetch schemas and refresh the generated client.
Generate from the lockfile
Run npx @usepapier/cli generate to rebuild the client from an existing lockfile.
Use the dashboard to publish template versions to your project’s environments. Keep .papier/papier.json and .papier/papier.lock.json in version control so the integration is reviewable with your code.
FROM DESIGN TO YOUR APP
Make room for
better messages.
Build the template together.
Ship it with a typed contract.