Render Template API

Last modified: May 16, 2025

This endpoint allows you to render images based on templates from your library by providing dynamic data to replace template elements.

POST Endpoint

https://api.bulkdesign.app/render/template

Authentication

Authentication is required using Bearer token with your API key:

Authorization: Bearer <YOUR_API_KEY>

Sample Request

curl --request POST \ --url https://api.bulkdesign.app/render/template \ --header 'Authorization: Bearer <YOUR_API_KEY>' \ --header 'Content-Type: application/json' \ --data '{ "templateId": "template-123456", "format": "jpg", "jsonData": { "headline": { "content": "Welcome to BulkDesign!" }, "profile-image": { "src": "https://example.com/profile.jpg" } }, "quality": 90 }'

Request Body

  • templateId (required) - The unique identifier for your template
  • format (optional) - Output format of the image (jpg, png, webp, pdf). Defaults to jpg
  • jsonData (required) - Values to replace in the template. Structure should match your template's replaceable elements
  • quality (optional) - Image quality (1-100, JPG only)
  • webhookUrl (optional) - URL to receive notification when rendering is complete (makes request asynchronous)

Synchronous vs Asynchronous Rendering

The API supports both synchronous and asynchronous rendering modes:

Synchronous Rendering (Default)

When no webhookUrl is provided, the request is processed synchronously. The API will wait for the rendering to complete before sending a response. This is suitable for simple templates with quick rendering times.

Asynchronous Rendering with Webhooks

When a webhookUrl is provided, the request becomes asynchronous:

  1. The API immediately returns a 202 Accepted response with a job ID
  2. The rendering process continues in the background
  3. When complete, the system sends a POST request to your webhookUrl

Example asynchronous request:

curl --request POST \ --url https://api.bulkdesign.app/render/template \ --header 'Authorization: Bearer <YOUR_API_KEY>' \ --header 'Content-Type: application/json' \ --data '{ "templateId": "template-123456", "format": "jpg", "jsonData": { "headline": { "content": "Welcome to BulkDesign!" } }, "quality": 90, "webhookUrl": "https://your-server.com/webhook" }'
Asynchronous Response (202 Accepted)
{ "status": "pending", "renderId": "job-id-123", "message": "Rendering started asynchronously. You will be notified via webhook when complete." }
Webhook Callback

When rendering completes, your webhook endpoint will receive a POST request with the following data:

On Success:

{ "status": "completed", "renderId": "job-id-123", "url": "https://api.bulkdesign.app/uploads/remotion/image-hash-123456.jpg" }

On Failure:

{ "status": "failed", "renderId": "job-id-123", "error": "Error message explaining what went wrong" }

Understanding jsonData Structure

The jsonData object should contain keys that match your template's element IDs, with nested properties matching the element's attributes:

{ "element-id": { "property": "value" } }

For example, to update text content and color:

{ "headline": { "content": "New Headline Text", "color": "#FF5733" } }

Supported Properties

Depending on the element type, different properties can be modified:

  • Text elements: text, color, fontSize, etc.
  • Image elements: src, alt, etc.
  • Shape elements: color, borderColor, etc.

Successful Response

A successful response returns a 200 status code with the URL to the rendered image:

{ "url": "https://api.bulkdesign.app/uploads/remotion/image-hash-123456.jpg" }

Error Response

Unsuccessful responses return appropriate status codes with error details:

{ "error": "Missing templateId in request body" }

Common error codes:

  • 400 - Bad request (missing parameters or invalid data)
  • 401 - Unauthorized (invalid API key)
  • 404 - Template not found

Credits Usage

Each successful render consumes one credit from your account. The system automatically tracks render history and credit usage.

Usage Considerations

Choosing Between Synchronous and Asynchronous

  • Use synchronous rendering for simple templates and when you need the result immediately
  • Use asynchronous rendering for:
    • Complex templates that take longer to render
    • Batch processing multiple renders
    • High-volume operations
    • Preventing timeouts on long-running renders

Webhook Requirements

When using asynchronous rendering:

  • Your webhook endpoint must be publicly accessible
  • It should respond with a 2xx status code to acknowledge receipt
  • It should be able to handle POST requests with JSON payloads
  • Consider implementing retry logic for webhook receiving

Image Caching

Rendered images are cached based on the request parameters. Identical requests will return the same image URL without consuming additional credits.

Image Retention

Rendered images are stored for 30 days by default. For longer retention, please contact support.

Rate Limiting

Rendered images are cached based on the request parameters. Identical requests will return the same image URL without consuming additional credits.

Detailed Property Reference

The following properties are supported for each element type in your templates. You can modify these properties through the jsonData parameter.

Common Properties (All Elements)

{ "element-id": { "height": 100, "width": 200, "left": 10, "top": 20, "color": "#FF5733", "rotate": 45, "scaleX": 1.2, "scaleY": 0.8, "opacity": 0.8, "backgroundColor": "#F5F5F5" } }
  • height - Element height in pixels
  • width - Element width in pixels
  • left - Horizontal position from the left edge
  • top - Vertical position from the top edge
  • color - General color property (used differently based on element type)
  • rotate - Rotation angle in degrees
  • scaleX - Horizontal scale factor
  • scaleY - Vertical scale factor
  • opacity - Transparency value between 0 and 1

Text Elements

{ "text-element-id": { "content": "New headline text", "fontSize": 24, "fontFamily": "Arial, sans-serif", "color": "#333333", "lineHeight": 1.5, "textAlign": "center", "fitMode": "fit", "bold": true, "italic": false, "underline": false, "letterSpacing": "1px", "strokeWidth": 1, "strokeColor": "#000000", "shadowColor": "rgba(0,0,0,0.3)", "shadowBlur": 5, "shadowOffsetX": 2, "shadowOffsetY": 2 } }
  • content - The text content
  • fontSize - Font size in pixels
  • fontFamily - Font family name(s)
  • color - Text color
  • lineHeight - Line height multiplier
  • textAlign - Text alignment ("left", "center", or "right")
  • fitMode - How the text should fit in its container ("fit", "fill", or "none")
  • bold - Whether text should be bold (true/false)
  • italic - Whether text should be italicized (true/false)
  • underline - Whether text should be underlined (true/false)
  • textDecoration - Text decoration (e.g., "underline", "line-through")
  • letterSpacing - Space between letters
  • wordSpacing - Space between words
  • strokeWidth - Width of text outline
  • strokeColor - Color of text outline
  • shadowColor - Color of text shadow
  • shadowBlur - Blur amount of text shadow
  • shadowOffsetX - Horizontal offset of text shadow
  • shadowOffsetY - Vertical offset of text shadow

Image Elements

{ "image-element-id": { "src": "https://example.com/new-image.jpg", "alt": "Description of image", "flipX": false, "flipY": false, "cornerRadius": 8, "borderWidth": 2, "borderColor": "#333333", "shadowColor": "rgba(0,0,0,0.3)", "shadowOffsetX": 3, "shadowOffsetY": 3, "shadowBlur": 5, "shadowOpacity": 0.5, "fitMode": "cover" } }
  • src - URL of the image
  • alt - Alternative text for the image
  • flipX - Whether to flip horizontally (true/false)
  • flipY - Whether to flip vertically (true/false)
  • cornerRadius - Radius for rounded corners
  • borderWidth - Width of image border
  • borderColor - Color of image border
  • shadowColor - Color of image shadow
  • shadowOffsetX - Horizontal offset of image shadow
  • shadowOffsetY - Vertical offset of image shadow
  • shadowBlur - Blur amount of image shadow
  • shadowOpacity - Opacity of image shadow
  • fitMode - How the image should fit in its container ("contain", "cover", "fill", or "none")

Shape Elements (Rectangle, Circle, Triangle, Ellipse, Pentagon)

{ "shape-element-id": { "fillColor": "#FF5733", "strokeColor": "#333333", "strokeWidth": 2, "borderRadius": 5 } }
  • fillColor - Fill color of the shape
  • strokeColor - Outline color of the shape
  • strokeWidth - Width of the shape outline
  • borderRadius - Radius for rounded corners (rectangles only)
  • radius - Radius of a circle (circles only)