proofsdocscomparepricinglog in

Documentation

Learn how to integrate proof.holdings

Core Primitives
The mental model in one page
API Reference
Complete API documentation
SDKs
Official client libraries
Smart Reuse
Skip re-verification with existing proofs
Multi-Profile System
Multiple public profiles per account
Message Templates
Custom branding and message templates per project
Comparison
vs SMS OTP, TOTP, WebAuthn
Pricing
Plans and pricing tiers
Security
Threat model and guarantees
MCP Server
167 tools for AI agents
Integrations
n8n, Zapier, Make, and custom integrations
Proof of Me
Anti-impersonation reverse verification via trusted Circle members
Proof of Delegation
A proven domain authorizing an artifact, and how to verify or withdraw it
Resources
GitHub Docs
Status

Message Templates

Custom message templates, one set per project


Overview

Templates customize the messages sent to people during verification, login, 2FA, confirmation and account-deletion flows over WhatsApp, Telegram, SMS and email. A template you have not set falls back to the Proof system default, so you only override what you want to change.

Every message belongs to exactly one project (a public profile — the sub-account it is sent for), and only that project's branding appears in it. Templates follow the same rule. A message is rendered from:

  1. The project's template — the one stored for that project, channel and message type.
  2. System default — Proof's own copy, when the project has no template of its own.

There is no account-wide template: a template saved for one project is never used by another. Projects are managed on their own endpoints and documented in Multi-Profile System, which also covers each project's name, logo, colour, email theme and support email — this page covers templates only.


Template Endpoints

Base URL: https://api.proof.holdings/api/v1/templates

These endpoints accept either an API key (Authorization: Bearer pk_live_…) or a dashboard session cookie. API-key callers need the templates:read scope to read and templates:write to write. Dashboard sessions additionally require a 2FA step-up before PUT and DELETE.

MethodEndpointPurpose
GET/api/v1/templatesList a project's templates and the available variables
GET/api/v1/templates/defaultsList Proof's system default templates
GET/api/v1/templates/:channel/:messageTypeGet one resolved template
PUT/api/v1/templates/:channel/:messageTypeCreate or update a template
DELETE/api/v1/templates/:channel/:messageTypeDelete a template (revert to the default)
POST/api/v1/templates/previewRender a draft against sample data
POST/api/v1/templates/renderRender a stored template with supplied variables

Choosing the Project

Every template operation works on one project, named by an optional ?profile_id query parameter: GET /api/v1/templates, GET/PUT/DELETE /api/v1/templates/:channel/:messageType, POST /api/v1/templates/preview and POST /api/v1/templates/render. Preview and render use the project's own name and support email for {{business_name}} and {{support_email}}.

GET /api/v1/templates/defaults returns the platform defaults, which are the same for every project.

CallerBehaviour
API key bound to a projectAlways that project. Naming a different project returns 403 profile_mismatch — a key cannot act outside its own binding.
Account-wide API key or dashboard sessionMay pass ?profile_id=<id> to name a project you own; one you do not own returns 403 profile_not_owned. Omit it to act on your primary project.

A bound key reaches only its own project everywhere else too — see Sub-accounts and API keys.

GET /api/v1/templates/:channel/:messageType reports which layer answered in a scope field (project or default), and names the project in profile_id.


Create or Update a Template

PUT /api/v1/templates/:channel/:messageType

URL Parameters

ParameterValues
channeltelegram, whatsapp, sms, email
messageTypeAny value from Message Types below

Request Body

ParameterTypeRequiredDescription
bodystringYesTemplate text with {{variables}} (1–2000 chars)
subjectstringNoEmail subject line (max 200 chars, email only)
button_textstringNoCTA button text (max 50 chars)
button_url_templatestringNoButton URL template (max 500 chars)

is_active is returned on template responses but is not accepted here — delete the template to stop using it.

No hard-coded project names

A template may name its brand only through {{business_name}}. A subject, body or button_text that spells out the name of one of your projects (its business name or display name, three characters or more, matched case-insensitively as a whole word) is refused with 400 template_hardcoded_name. The same word inside a longer word is not a match.

Example: a custom WhatsApp verification message

bash
curl -X PUT https://api.proof.holdings/api/v1/templates/whatsapp/verification_request \
  -H "Authorization: Bearer pk_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "Welcome to {{business_name}}! Your verification code is {{code}}. This code expires in {{expires_in}}."
  }'

Example: a custom email template for one project

bash
curl -X PUT "https://api.proof.holdings/api/v1/templates/email/verification_request?profile_id=64a1b2c3d4e5f6a7b8c9d0e1" \
  -H "Cookie: session=eyJ..." \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "Verify your email for {{business_name}}",
    "body": "Hi there,\n\nPlease verify your email address ({{user_identifier}}) by entering this code:\n\n{{code}}\n\nThis code expires in {{expires_in}}.\n\nIf you did not request this, please ignore this email.\n\n— The {{business_name}} Team",
    "button_text": "Verify Email"
  }'

Preview a Template

POST /api/v1/templates/preview

Render a draft against sample data before saving it. Nothing is stored. Pass ?profile_id to preview it with that project's name and support email.

Request Body

ParameterTypeRequiredDescription
channelstringYestelegram, whatsapp, sms, email
message_typestringYesSee Message Types
bodystringYesTemplate body to preview
subjectstringNoEmail subject to preview
button_textstringNoButton text to preview
button_url_templatestringNoButton URL to preview
bash
curl -X POST https://api.proof.holdings/api/v1/templates/preview \
  -H "Authorization: Bearer pk_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "email",
    "message_type": "verification_request",
    "subject": "Verify your email for {{business_name}}",
    "body": "Your code is {{code}}. Expires in {{expires_in}}."
  }'

Delete a Template

DELETE /api/v1/templates/:channel/:messageType

Removes the project's custom template. Later messages from that project on that channel and message type use the Proof system default.

bash
curl -X DELETE https://api.proof.holdings/api/v1/templates/whatsapp/verification_request \
  -H "Authorization: Bearer pk_live_your_api_key_here"

Message Types

TypeWhen Sent
verification_requestSomeone needs to verify an asset
verification_successAsset successfully verified
verification_expiredVerification challenge expired
login_requestLogin verification initiated
login_successLogin completed
2fa_request2FA challenge sent
2fa_success2FA completed
account_deletion_requestAccount deletion requested
account_deletion_successAccount deletion completed
confirmation_requestAn approval was requested
confirmation_approvedAn approval was granted
confirmation_deniedAn approval was refused

Template Variables

Use {{variable_name}} in the body (and in an email subject).

VariableDescription
{{business_name}}The project's name
{{code}}Verification code (when applicable)
{{expires_in}}Time until expiry (e.g. "10 minutes")
{{user_identifier}}Masked phone or email
{{channel}}Current channel name
{{callback_url}}Success callback URL
{{support_email}}The project's support email
{{action_label}}The action requested (e.g. "Two-Factor Authentication")
{{action_title}}Short title of what was requested
{{action_description}}What the recipient is being asked to do
{{amount}}Amount, for approval-type actions
{{currency}}Currency, for approval-type actions
{{entity}}Entity or counterparty, for approval-type actions

The six action variables are populated for confirmation and 2FA flows; they render empty elsewhere.


See Also

TopicDocumentation
Managing projects and their brandingMulti-Profile System
Full endpoint referenceAPI Reference

Related

API ReferenceIntegrations
Last updated October 15, 2026
Proof Holdings

The verification API for humans and AI agents — every verification a signed proof you hold.

A service of LT Telecom (UAB "LT telekomunikacijos")

PrivacyTermsDPASubprocessorsStatusGitHubLinkedIn