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.
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 }'
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": 1450239 }10}
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;" />45<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 });2324 const result = await response.json();25 if (!response.ok) throw new Error(result.error || 'Request failed');2627 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';23export 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);78 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 });2829 const result = await response.json();30 if (!response.ok) throw new Error(result.error || 'Request failed');3132 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 };3940 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_keyFor public templates embedded in <img> tags, you may pass apiKey as a query parameter instead.
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).
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}
1{2 "templateId": "abc123xyz",3 "data": {4 "headline_text": "Summer Sale",5 "hero_image": "https://cdn.example.com/banner.jpg"6 }7}
List Templates
/api/v1/templatesRetrieves 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)
/api/v1/generateRenders 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
| Field | Type | Description |
|---|---|---|
| templateId | string | Required. ID of a saved template. |
| data | object | Layer values keyed by element id. Image layers accept HTTPS URLs or base64 data URIs. |
| format | string | Optional. png, jpeg, or pdf. Default: png. |
| quality | string | Optional. original, hd, or 4k. Pro plan required for HD/4K. Basic plan exports include a watermark at original quality. |
| skipUpload | boolean | Optional. 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": 1450239 }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": 1450239 }10}
Errors
| Status | Meaning |
|---|---|
| 400 | Missing templateId |
| 401 | Invalid or missing API key / session |
| 404 | Template not found |
Generate Image (GET)
/api/v1/generateRenders 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
| Parameter | Required | Description |
|---|---|---|
| templateId | Yes | The ID of the template. |
| format | No | png, jpeg, or pdf. Default: png. |
| quality | No | original, hd, or 4k. Watermark rules follow the template owner's plan. |
| apiKey | Private only | API key for private templates. Can also use the Authorization header. |
| {layer_id} | No | Any 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<img2 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<img2 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
/api/v1/uploadUploads an image to CDN storage and returns a public URL plus a BlurHash placeholder. Images only, max 10MB.
Request Body (Multipart)
| Field | Type | Description |
|---|---|---|
| file | File | Image file (JPEG, PNG, WebP, etc.). Max 10MB. |
| resourceType | string | Optional. '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
/api/v1/bulk-exportGenerates 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)
| Field | Type | Description |
|---|---|---|
| templateId | string | ID of the template to use. |
| data | JSON string | Required. Stringified array of row objects. Keys should match element IDs or labels. |
| format | string | Optional. png, jpeg, or pdf. Default: png. |
| quality | string | Optional. Same values as generate endpoint. Default: original. |
| filenameTemplate | string | Optional. 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": 505}