Introduction

Welcome to Templify Docs

Templify is a developer-first platform for programmatically generating images. Create dynamic templates using our drag-and-drop editor and populate them with data via our REST API.

Quick Start

Generate your first image

Create a template in the editor, copy its ID from the dashboard, then call POST /api/v1/generate with your API key. Keys in data must match layer IDs from the template.

1curl -X POST "/api/v1/generate" \
2 -H "Authorization: Bearer tf_your_api_key_here" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "templateId": "your_template_id",
6 "data": {
7 "text_layer_id": "Hello World",
8 "image_layer_id": "https://example.com/photo.jpg"
9 },
10 "format": "png",
11 "quality": "original"
12 }'
Success response
1{
2 "status": "success",
3 "url": "https://res.cloudinary.com/.../image.png",
4 "meta": {
5 "width": 1200,
6 "height": 630,
7 "format": "png",
8 "size": 145023
9 }
10}
Integrations

Client Integrations

You can easily integrate Templify into your web applications. Below are examples for HTML/Vanilla JS and React.

HTML / Vanilla JS

1<!-- index.html -->
2<button id="generateBtn">Generate Image</button>
3<img id="resultImage" style="display: none; max-width: 100%; margin-top: 20px;" />
4
5<script>
6 document.getElementById('generateBtn').addEventListener('click', async () => {
7 try {
8 const response = await fetch('/api/v1/generate', {
9 method: 'POST',
10 headers: {
11 'Authorization': 'Bearer tf_your_api_key_here',
12 'Content-Type': 'application/json'
13 },
14 body: JSON.stringify({
15 templateId: 'your_template_id',
16 data: {
17 text_layer_id: 'My Dynamic Title',
18 image_layer_id: 'https://example.com/photo.jpg'
19 },
20 format: 'png'
21 })
22 });
23
24 const result = await response.json();
25 if (!response.ok) throw new Error(result.error || 'Request failed');
26
27 if (result.url) {
28 document.getElementById('resultImage').src = result.url;
29 document.getElementById('resultImage').style.display = 'block';
30 } else if (result.image) {
31 document.getElementById('resultImage').src = result.image;
32 document.getElementById('resultImage').style.display = 'block';
33 }
34 } catch (error) {
35 console.error('Error:', error);
36 }
37 });
38</script>

React

1import { useState } from 'react';
2
3export default function ImageGenerator() {
4 const [imageUrl, setImageUrl] = useState<string | null>(null);
5 const [loading, setLoading] = useState(false);
6 const [error, setError] = useState<string | null>(null);
7
8 const generateImage = async () => {
9 setLoading(true);
10 setError(null);
11 try {
12 const response = await fetch('/api/v1/generate', {
13 method: 'POST',
14 headers: {
15 'Authorization': 'Bearer tf_your_api_key_here',
16 'Content-Type': 'application/json'
17 },
18 body: JSON.stringify({
19 templateId: 'your_template_id',
20 data: {
21 text_layer_id: 'React Generated',
22 avatar_layer_id: 'https://example.com/avatar.jpg'
23 },
24 format: 'png',
25 quality: 'original'
26 })
27 });
28
29 const result = await response.json();
30 if (!response.ok) throw new Error(result.error || 'Request failed');
31
32 setImageUrl(result.url || result.image || null);
33 } catch (err) {
34 setError(err instanceof Error ? err.message : 'Failed to generate');
35 } finally {
36 setLoading(false);
37 }
38 };
39
40 return (
41 <div>
42 <button onClick={generateImage} disabled={loading}>
43 {loading ? 'Generating...' : 'Generate Image'}
44 </button>
45 {error && <p>{error}</p>}
46 {imageUrl && <img src={imageUrl} alt="Generated" />}
47 </div>
48 );
49}

Authentication

Templify uses API keys to authenticate requests. You can view and manage your API keys in the API Keys section of your dashboard. Browser requests from the dashboard can also use your signed-in session cookie.

Authorization Header

Send your key as a Bearer token on POST requests and on private GET requests:

Authorization: Bearer tf_your_api_key

For public templates embedded in <img> tags, you may pass apiKey as a query parameter instead.

Template Structure

The Template Object

A template consists of a base image and dynamic layers. When generating, the data object maps each layer's id to the value you want rendered (text, image URL, or base64 data URI).

Find layer IDs in the editor inspector under each field's ID, or from the API modal on a saved template. Bulk export also accepts column headers that match a layer label (case-insensitive).
example_template.json
1{
2 "id": "abc123xyz",
3 "name": "Social Media Post",
4 "baseImage": "https://...",
5 "elements": [
6 {
7 "id": "headline_text",
8 "type": "text",
9 "formConfig": {
10 "label": "Headline",
11 "placeholder": "Enter headline..."
12 }
13 },
14 {
15 "id": "hero_image",
16 "type": "image",
17 "formConfig": {
18 "label": "Hero Image"
19 }
20 }
21 ]
22}
matching generate payload
1{
2 "templateId": "abc123xyz",
3 "data": {
4 "headline_text": "Summer Sale",
5 "hero_image": "https://cdn.example.com/banner.jpg"
6 }
7}
API Reference

List Templates

GET/api/v1/templates

Retrieves a list of all templates owned by the authenticated user.

Response Example

1[
2 {
3 "id": "tmpl_123",
4 "name": "Newsletter Header",
5 "visibility": "public",
6 "updatedAt": "2024-01-01T12:00:00Z"
7 }
8]

Generate Image (POST)

POST/api/v1/generate

Renders a template with the supplied layer data. By default the image is uploaded to CDN storage and a public URL is returned. Identical requests are cached until the template is updated.

Request Body

FieldTypeDescription
templateIdstringRequired. ID of a saved template.
dataobjectLayer values keyed by element id. Image layers accept HTTPS URLs or base64 data URIs.
formatstringOptional. png, jpeg, or pdf. Default: png.
qualitystringOptional. original, hd, or 4k. Pro plan required for HD/4K. Basic plan exports include a watermark at original quality.
skipUploadbooleanOptional. When true, skips CDN upload and returns a base64 image field instead of url.

Example Request

1curl -X POST "/api/v1/generate" \
2 -H "Authorization: Bearer tf_your_api_key" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "templateId": "your_template_id",
6 "data": {
7 "headline_text": "Hello World",
8 "hero_image": "https://example.com/photo.jpg"
9 },
10 "format": "png",
11 "quality": "hd"
12 }'

Response (URL)

1{
2 "status": "success",
3 "url": "https://res.cloudinary.com/.../image.png",
4 "meta": {
5 "width": 1200,
6 "height": 630,
7 "format": "png",
8 "size": 145023
9 }
10}

Response (skipUpload)

1{
2 "status": "success",
3 "image": "data:image/png;base64,iVBORw0KGgo...",
4 "meta": {
5 "width": 1200,
6 "height": 630,
7 "format": "png",
8 "size": 145023
9 }
10}

Errors

StatusMeaning
400Missing templateId
401Invalid or missing API key / session
404Template not found

Generate Image (GET)

GET/api/v1/generate

Renders a template and returns the raw image file (not JSON). Ideal for <img src="..."> embeds and Open Graph tags. Public templates can be accessed without authentication. Private templates require an API key or signed-in session.

Query Parameters

ParameterRequiredDescription
templateIdYesThe ID of the template.
formatNopng, jpeg, or pdf. Default: png.
qualityNooriginal, hd, or 4k. Watermark rules follow the template owner's plan.
apiKeyPrivate onlyAPI key for private templates. Can also use the Authorization header.
{layer_id}NoAny other query parameter is passed as layer data (URL-encoded values).

cURL Example

1curl "/api/v1/generate?templateId=your_template_id&headline_text=Hello%20World&hero_image=https%3A%2F%2Fexample.com%2Fphoto.jpg&format=png" \
2 -H "Authorization: Bearer tf_your_api_key" \
3 --output result.png

HTML Embed (public template)

1<img
2 src="/api/v1/generate?templateId=your_template_id&headline_text=Dynamic%20Title&format=png"
3 alt="Generated image"
4 width="1200"
5 height="630"
6/>

HTML Embed (private template)

1<img
2 src="/api/v1/generate?templateId=your_template_id&headline_text=Dynamic%20Title&apiKey=tf_your_api_key&format=png"
3 alt="Generated image"
4/>

Response

Returns binary image data with Content-Type: image/png (or jpeg/pdf) and Cache-Control: public, max-age=3600.

Upload Asset

POST/api/v1/upload

Uploads an image to CDN storage and returns a public URL plus a BlurHash placeholder. Images only, max 10MB.

Request Body (Multipart)

FieldTypeDescription
fileFileImage file (JPEG, PNG, WebP, etc.). Max 10MB.
resourceTypestringOptional. 'image', 'video', 'raw', or 'auto'. Defaults to 'auto'.

Example

1curl -X POST /api/v1/upload \
2 -H "Authorization: Bearer tf_your_api_key" \
3 -F "file=@/path/to/your/image.png"

Response Example

1{
2 "status": "success",
3 "url": "https://res.cloudinary.com/.../image.png",
4 "blurhash": "L6PZfSi_.AyE_3t7t7R**0o#DgR4"
5}

Bulk Export

POST/api/v1/bulk-export

Generates multiple images from one template in a single request. Send a JSON array of row objects; each row is mapped to layer IDs (or matching layer labels). Returns a ZIP file URL. Maximum 50 rows per request.

Request Body (Multipart)

FieldTypeDescription
templateIdstringID of the template to use.
dataJSON stringRequired. Stringified array of row objects. Keys should match element IDs or labels.
formatstringOptional. png, jpeg, or pdf. Default: png.
qualitystringOptional. Same values as generate endpoint. Default: original.
filenameTemplatestringOptional. Output filename pattern. Use {{index}} or {{column_name}}. Default: "image-{{index}}".

Example

1curl -X POST "/api/v1/bulk-export" \
2 -H "Authorization: Bearer tf_your_api_key" \
3 -F "templateId=your_template_id" \
4 -F 'data=[{"headline_text":"Alice","hero_image":"https://example.com/a.jpg"},{"headline_text":"Bob","hero_image":"https://example.com/b.jpg"}]' \
5 -F "format=png" \
6 -F "filenameTemplate=ticket-{{headline_text}}"

Response Example

1{
2 "status": "success",
3 "url": "https://res.cloudinary.com/.../bulk_export.zip",
4 "count": 50
5}