SendrinSendrin Docsv1.0 (Current)
Platform Guides

Events & Templates

Learn how to define versioned event contracts, design multi-channel templates in Template Studio, and dispatch notifications with variable interpolation.

Events & Templates Architecture

In Sendrin, sending a notification is decoupled into two clean primitives:

[ Backend Application ] 
       │
       ▼ (Dispatches notification with event_key + data payload)
[ Event Contract (/events) ]
       │ ── Validates payload against JSON Schema
       │ ── Enforces allowed delivery channels
       ▼
[ Published Template (/templates) ]
       │ ── Interpolates {{variables}} into HTML / SMS / WhatsApp / In-App
       ▼
[ Transport Provider (Postal SMTP / Meta Cloud / SMS Gateway) ]
       │
       ▼
[ Recipient Inbox / Device ]
  1. Event Contract (/events): A versioned business contract (e.g. order.confirmed, user.welcome) that declares required payload properties (e.g. customer_name, order_id, amount) and allowed channels.
  2. Channel Template (/templates): The presentation layer for a specific channel (Email HTML, SMS text, WhatsApp approved template, or In-App banner) that interpolates variables using Handlebars syntax: {{customer_name}}.

Step 1: Register an Event Contract

Before creating a template, define the event contract in the Sendrin Console under Events.

1-Click Starter Presets

The Console provides pre-configured contracts with auto-filled JSON schemas:

Starter PresetEvent KeyDefault ChannelsKey Variables
User Welcome & Onboardinguser.welcomeemail, in_app{{user_name}}, {{login_url}}
Order Confirmationorder.confirmedemail, sms, whatsapp{{customer_name}}, {{order_id}}, {{total_amount}}, {{tracking_url}}
Billing & Invoice Readybilling.invoice_readyemail{{customer_name}}, {{invoice_number}}, {{amount_due}}, {{pdf_url}}
Password Resetauth.password_resetemail{{user_name}}, {{reset_link}}, {{expires_in_minutes}}
Custom ContractUser-definedFlexibleCustom defined schema

Example JSON Schema

Here is the JSON Schema for an order.confirmed contract:

{
  "type": "object",
  "required": ["customer_name", "order_id", "total_amount"],
  "properties": {
    "customer_name": { "type": "string", "description": "Customer full name" },
    "order_id": { "type": "string", "description": "Order identifier #" },
    "total_amount": { "type": "string", "description": "Total amount (e.g. ₹1,499)" },
    "tracking_url": { "type": "string", "description": "Shipment tracking URL" }
  },
  "additionalProperties": true
}

[!TIP] Setting "additionalProperties": true is recommended. This allows your backend to pass metadata fields (such as timestamps or internal IDs) without failing schema validation.


Step 2: Inspecting Created Events

Once created, click any event row in the Events list to open the Event Details Drawer:

  • Schema Variables: Displays all variables, data types, and required badges.
  • Sample Payload: Automatically synthesizes realistic mock data based on the schema for quick testing.
  • API Integration Snippet: Generates ready-to-run copy-paste snippets in cURL, Node.js, and Python.
  • Design Template: Direct shortcut to open Template Studio with this event pre-selected.

Step 3: Designing Templates in Template Studio

Navigate to Templates and click + Open Studio (or click Design Template from an Event):

  1. Select the Event: Choose the event contract (e.g., order.confirmed).
  2. Select the Channel: Email, SMS, WhatsApp, or In-App.
  3. Use Handlebars Variables: Insert dynamic fields using {{variable_name}}.

Email Template Example

Subject line:

Order Confirmed: #{{order_id}}

HTML Content:

<div style="font-family: sans-serif; max-width: 600px; margin: 0 auto; padding: 20px;">
  <h2>Thank you for your order, {{customer_name}}!</h2>
  <p>We've received order <strong>#{{order_id}}</strong> for a total of <strong>{{total_amount}}</strong>.</p>
  <div style="margin: 30px 0;">
    <a href="{{tracking_url}}" style="background: #ff6b00; color: #fff; padding: 12px 24px; text-decoration: none; border-radius: 6px; font-weight: bold;">
      Track Your Package
    </a>
  </div>
  <p style="color: #64748b; font-size: 13px;">If you have any questions, reply directly to this email.</p>
</div>

The 3-Step Template Lifecycle

Templates follow an immutable versioning lifecycle to ensure production safety:

[ 1. Draft ]  ──(Save changes)──>  [ 2. Validate ]  ──(Validate Schema)──>  [ 3. Publish to Live ]
  1. Draft: Create and edit content. Drafts cannot be dispatched by the live API.
  2. Validate: Verifies that all variables used in the template exist in the event schema.
  3. Publish to Live: Promotes the validated version to the active live version. Only published versions are sent by POST /api/v1/notifications.

Step 4: Dispatching Notifications in Code

Once your template is published, dispatch notifications using your Application API Key.

cURL

curl --request POST 'https://api.sendrin.com/api/v1/notifications' \
  --header "Authorization: Bearer $SENDRIN_API_KEY" \
  --header 'Content-Type: application/json' \
  --header "Idempotency-Key: idemp_order_1001" \
  --data '{
    "event_key": "order.confirmed",
    "channel": "email",
    "recipient": {
      "email": "customer@example.com"
    },
    "data": {
      "customer_name": "Ravi Kant",
      "order_id": "ORD-98214",
      "total_amount": "₹2,499",
      "tracking_url": "https://sendrin.com/track/ORD-98214"
    }
  }'

Node.js (TypeScript / JavaScript)

const response = await fetch("https://api.sendrin.com/api/v1/notifications", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.SENDRIN_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": `order_${orderId}`,
  },
  body: JSON.stringify({
    event_key: "order.confirmed",
    channel: "email",
    recipient: {
      email: customerEmail,
    },
    data: {
      customer_name: customerName,
      order_id: orderId,
      total_amount: "₹2,499",
      tracking_url: `https://sendrin.com/track/${orderId}`,
    },
  }),
});

const result = await response.json();
console.log("Notification accepted:", result.id, "Status:", result.status);

Python (requests)

import os
import requests

response = requests.post(
    "https://api.sendrin.com/api/v1/notifications",
    headers={
        "Authorization": f"Bearer {os.environ['SENDRIN_API_KEY']}",
        "Content-Type": "application/json",
        "Idempotency-Key": f"order_{order_id}",
    },
    json={
        "event_key": "order.confirmed",
        "channel": "email",
        "recipient": {
            "email": "customer@example.com"
        },
        "data": {
            "customer_name": "Ravi Kant",
            "order_id": "ORD-98214",
            "total_amount": "₹2,499",
            "tracking_url": "https://sendrin.com/track/ORD-98214"
        },
    },
    timeout=30,
)

result = response.json()
print(f"Accepted notification: {result['id']}")

Troubleshooting & Common Errors

422 Unprocessable Entity - schema_validation_failed

  • Cause: The data payload sent to /notifications did not match the JSON schema registered on the event.
  • Fix: Check the Event Details Drawer in the Console under Schema Variables to verify all required variables are supplied with matching types.

409 Conflict - template_not_published

  • Cause: The template mapped to the event and channel is currently in draft state.
  • Fix: Open the template in Template Studio, click Validate, and then click Publish to Live.

401 Unauthorized - invalid_api_key

  • Cause: The API key header is missing or incorrect.
  • Fix: Under Credentials, copy your application secret key (sendrin_live_sk_...) and ensure it is stored as SENDRIN_API_KEY on your backend.

On this page