Skip to content
Pidgely Docs

Guides

Templates

Store email content once with typed variables and fallbacks, edit drafts safely, publish versions and send with template id or alias.

View as Markdown

A template holds the subject, HTML, text and (optionally) sender of an email, with variables filled in at send time. Templates have a draft you can edit freely and published versions that sends use, so editing never changes what goes out until you publish.

Create a template

Node.js
import { Pidgely } from 'pidgely';

const pidgely = new Pidgely(process.env.PIDGELY_API_KEY);

const { data, error } = await pidgely.templates.create({
  name: 'Order confirmation',
  alias: 'order-confirmation',
  from: 'Acme <orders@acme.com>',
  subject: 'Order {{{ORDER_ID}}} confirmed',
  html: '<p>Hi {{{CUSTOMER_NAME|there}}}, your order {{{ORDER_ID}}} totals ${{{TOTAL}}}.</p>',
  variables: [
    {
      key: 'ORDER_ID',
      type: 'string',
    },
    {
      key: 'TOTAL',
      type: 'number',
      fallbackValue: 0,
    },
    {
      key: 'CUSTOMER_NAME',
      type: 'string',
      fallbackValue: 'there',
    },
  ],
});
console.log(data ?? error);
Python
import os
import pidgely

pidgely.api_key = os.environ["PIDGELY_API_KEY"]

result = pidgely.Templates.create({
    "name": "Order confirmation",
    "alias": "order-confirmation",
    "from": "Acme <orders@acme.com>",
    "subject": "Order {{{ORDER_ID}}} confirmed",
    "html": "<p>Hi {{{CUSTOMER_NAME|there}}}, your order {{{ORDER_ID}}} totals ${{{TOTAL}}}.</p>",
    "variables": [
        {
            "key": "ORDER_ID",
            "type": "string",
        },
        {
            "key": "TOTAL",
            "type": "number",
            "fallback_value": 0,
        },
        {
            "key": "CUSTOMER_NAME",
            "type": "string",
            "fallback_value": "there",
        },
    ],
})
print(result)
PHP
<?php

require __DIR__ . '/vendor/autoload.php';

$pidgely = Pidgely::client(getenv('PIDGELY_API_KEY'));

$result = $pidgely->templates->create([
    'name' => 'Order confirmation',
    'alias' => 'order-confirmation',
    'from' => 'Acme <orders@acme.com>',
    'subject' => 'Order {{{ORDER_ID}}} confirmed',
    'html' => '<p>Hi {{{CUSTOMER_NAME|there}}}, your order {{{ORDER_ID}}} totals ${{{TOTAL}}}.</p>',
    'variables' => [
        [
            'key' => 'ORDER_ID',
            'type' => 'string',
        ],
        [
            'key' => 'TOTAL',
            'type' => 'number',
            'fallback_value' => 0,
        ],
        [
            'key' => 'CUSTOMER_NAME',
            'type' => 'string',
            'fallback_value' => 'there',
        ],
    ],
]);
var_dump($result);
Go
package main

import (
	"context"
	"fmt"
	"os"

	"github.com/pidgely/pidgely-go"
)

func main() {
	ctx := context.Background()
	client := pidgely.NewClient(os.Getenv("PIDGELY_API_KEY"))

	result, err := client.Templates.Create(ctx, &pidgely.CreateTemplateRequest{
		Name:      "Order confirmation",
		Alias:     "order-confirmation",
		From:      "Acme <orders@acme.com>",
		Subject:   "Order {{{ORDER_ID}}} confirmed",
		Html:      "<p>Hi {{{CUSTOMER_NAME|there}}}, your order {{{ORDER_ID}}} totals ${{{TOTAL}}}.</p>",
		Variables: []pidgely.TemplateVariableInput{
		{
			Key:  "ORDER_ID",
			Type: "string",
		},
		{
			Key:           "TOTAL",
			Type:          "number",
			FallbackValue: 0,
		},
		{
			Key:           "CUSTOMER_NAME",
			Type:          "string",
			FallbackValue: "there",
		},
	},
	})
	if err != nil {
		panic(err)
	}
	fmt.Println(result)
}
Ruby
require "pidgely"

Pidgely.api_key = ENV["PIDGELY_API_KEY"]

result = Pidgely::Templates.create({
  name: "Order confirmation",
  alias: "order-confirmation",
  from: "Acme <orders@acme.com>",
  subject: "Order {{{ORDER_ID}}} confirmed",
  html: "<p>Hi {{{CUSTOMER_NAME|there}}}, your order {{{ORDER_ID}}} totals ${{{TOTAL}}}.</p>",
  variables: [
    {
      key: "ORDER_ID",
      type: "string"
    },
    {
      key: "TOTAL",
      type: "number",
      fallback_value: 0
    },
    {
      key: "CUSTOMER_NAME",
      type: "string",
      fallback_value: "there"
    }
  ]
})
puts result
cURL
curl -X POST 'https://api.pidgely.com/templates' \
  -H "Authorization: Bearer $PIDGELY_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Order confirmation",
  "alias": "order-confirmation",
  "from": "Acme <orders@acme.com>",
  "subject": "Order {{{ORDER_ID}}} confirmed",
  "html": "<p>Hi {{{CUSTOMER_NAME|there}}}, your order {{{ORDER_ID}}} totals ${{{TOTAL}}}.</p>",
  "variables": [
    {
      "key": "ORDER_ID",
      "type": "string"
    },
    {
      "key": "TOTAL",
      "type": "number",
      "fallback_value": 0
    },
    {
      "key": "CUSTOMER_NAME",
      "type": "string",
      "fallback_value": "there"
    }
  ]
}'
  • name (1–200 characters) and html are required. from and reply_to are validated as addresses when present.
  • alias is an optional, unique, human-readable key (^[A-Za-z0-9][A-Za-z0-9_.-]{0,99}$, not shaped like a UUID). Every endpoint accepts the id or the alias. A duplicate alias gets 409 alias_taken.

Variables

Variables use triple braces in subject, html and text:

Syntax Result
{{{ORDER_ID}}} The value passed at send time (or the declared fallback)
{{{CUSTOMER_NAME|there}}} The value, or there when none is available
{{ ORDER_ID }} Left as is (double braces are not variables)

Spaces inside the braces are allowed. In html, values are HTML-escaped; in subject and text they are inserted as is.

Declare up to 50 variables with a key (^[A-Za-z0-9_]{1,50}$), a type (string or number) and an optional fallback_value of that type. The names FIRST_NAME, LAST_NAME, EMAIL and UNSUBSCRIBE_URL are reserved.

Drafts and publishing

  1. Every create or update changes the draft and sets has_unpublished_versions: true.
  2. POST /templates/{id}/publish turns the draft into an immutable published version.
  3. Sends always use the latest published version. A template that was never published can't be used (template.id: only published templates can be used to send).

Duplicate creates a draft copy named <name> (copy), handy for A/B variants.

Send with a template

JSON
{
  "to": ["steve@example.com"],
  "template": {
    "id": "order-confirmation",
    "variables": { "ORDER_ID": "1234", "TOTAL": 59.9, "CUSTOMER_NAME": "Steve" }
  }
}
  • template.id takes the id or the alias.
  • template can't be combined with html or text: the template's bodies are always used.
  • from, subject and reply_to come from the template only when the request leaves them empty: values in the request win.
  • Each variable resolves to the value you pass, then the declared fallback_value, then the inline |fallback. If any is still missing, the send fails with 422 validation_error and template.variables: missing value for ORDER_ID.
  • String values can be up to 2,000 characters; numbers are formatted as given. A string passed to a number variable fails with must be a number. Keys you didn't declare are treated as strings.

Templates work in batch sends too, each email with its own variables.