Templates
In API v1, all outbound SMS messages are validated against an approved SMS Template. Templates protect sender reputation, guarantee fast carrier delivery, and automatically determine priority routing and token pricing.
How Templates Work
A template consists of a unique slug (lowercase alphanumeric, dashes, or underscores), a rawText body containing {placeholder} variables, and a paramRules JSON object that strictly defines the format of each placeholder.
Scopes: Organization vs Public
ORGANIZATION(Default): Private to your organization. Can optionally be restricted to a single application viaappId.PUBLIC: Shared across all organizations on Emess once approved. If your organization defines a template with the same slug as a public template, yourORGANIZATIONtemplate takes precedence unless you explicitly passscope: "PUBLIC"when sending.
[{app_name}] for clear brand attribution and phishing mitigation. The gateway automatically injects your application's registered name into {app_name} at runtime. You do not need to provide app_name in your request params (supplying it directly will be rejected to prevent caller spoofing).Placeholders & Parameter Rules
Every placeholder extracted from rawText (matching /{([a-zA-Z0-9_]+)}/) must have a corresponding rule entry in paramRules.
Supported Rule Types
| Type | Required Rule Properties | Validation Behavior |
|---|---|---|
| digits | Either exact length (int > 0) OR both min and max (integers) | Digits only (0-9). Ideal for OTPs and PIN codes (e.g. { "type": "digits", "length": 6 }). |
| number | Both min and max (numeric value bounds) | Integer or decimal numbers within [min, max]. Ideal for currency amounts or quantities. |
| alphanumeric | Both min and max (character length bounds) | Letters and numbers only (a-zA-Z0-9) with length between min and max. Ideal for order/reference IDs. |
| string | max (positive integer, max 64) | Any non-empty text up to max characters (cannot exceed 64 characters). |
Review Lifecycle & Pricing
- Submission (
PENDING): When you create a template via the dashboard orPOST /api/v1/templates, its initial status isPENDING. While unapproved (PENDINGorREJECTED), re-POSTing to the sameslugupdates the existing template and resets it toPENDING. - Approval (
APPROVED): Upon approval, Emess compiles a validation regex, locks the template from direct edits (returning409 Conflictif you try to overwrite an approved slug), and assigns itspriorityTier(CRITICAL,STANDARD, orBULK) andtokenMultiplier(defaults: 4x forCRITICAL, 2x forSTANDARD, 1x forBULK). - Token Calculation: Each message sent using the template deducts
Math.ceil(segments × tokenMultiplier)tokens.
POST/api/v1/templates
Create a new SMS template. For backward compatibility, POST /api/v1/templates also acts as a legacy upsert if an unapproved (PENDING or REJECTED) template with the same slug already exists (prefer PATCH /api/v1/templates/:slug for partial edits). Calling POST or PATCH on an APPROVED slug returns 409 Conflict.
Parameters (Body)
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Human-readable template name |
| slug | string | Yes | Unique identifier (lowercase alphanumeric, dashes, underscores: ^[a-z0-9_-]+$) |
| rawText | string | Yes | Template body with {placeholder} variables |
| paramRules | object | When placeholders exist | Validation rule definition for each placeholder |
| scope | enum | No (ORGANIZATION) | ORGANIZATION or PUBLIC |
| priorityTier | enum | No | Requested tier: CRITICAL, STANDARD, or BULK |
| appId | string | No | Optional App ID to restrict this template to a specific app |
| tags | string[] | No | Array of category tags (e.g. ["security", "otp"]), max 16 characters each |
Example Request
{"name": "Payment Confirmation","slug": "payment_receipt","scope": "ORGANIZATION","priorityTier": "STANDARD","rawText": "Hello {customer_name}, your payment of {amount} USD (Ref: {ref_id}) is confirmed. Code: {pin}","paramRules": {"customer_name": { "type": "string", "max": 24 },"amount": { "type": "number", "min": 1, "max": 10000 },"ref_id": { "type": "alphanumeric", "min": 6, "max": 12 },"pin": { "type": "digits", "length": 4 }}}
PATCH/api/v1/templates/:slug
Partially update an unapproved (PENDING or REJECTED) organization template. All body fields (name, rawText, paramRules, appId, priorityTier) are optional. The merged rawText and paramRules are re-validated, the status is reset to PENDING, and any previous rejectionReason / rejectionNotes are cleared.
- 403 Forbidden:
PUBLICtemplates cannot be edited via this endpoint. - 409 Conflict:
APPROVEDtemplates are locked and cannot be modified directly. - 422 Unprocessable Entity: Merged placeholders and
paramRulesfailed validation.
// PATCH /api/v1/templates/payment_receipt{"rawText": "Hello {customer_name}, payment of {amount} USD confirmed.","priorityTier": "CRITICAL"}
GET/api/v1/templates
List all templates belonging to your organization as well as all APPROVED public templates.
Tag Filtering
Filter templates by category using the tag or tags query parameter. You can specify a single tag or comma-separated tags (each tag max 16 characters).
GET /api/v1/templates?tag=otp— Returns templates tagged withotp.GET /api/v1/templates?tags=security,authentication— Returns templates matching either category.
Common categories include: authentication, security, billing, transactional, logistics, reminder, reservation, and account.
GET/api/v1/templates/:slug
Fetch a single template by its slug. Pass query parameter ?scope=public (or ?public=true) to inspect a public template instead of your organization's template.
DELETE/api/v1/templates/:slug
Delete a template owned by your organization by its slug.