Rendering API
The Canvelete (opens in a new tab) Rendering API is where the magic happens. You've created beautiful designs in our editor, and now it's time to turn them into actual images, PDFs, and other formats that you can use in your applications.
Send us a design ID along with any dynamic data you want to inject, and we'll send back a high-quality rendered image. Whether you need one image or thousands, we've got you covered.
Getting Started
Before we dive into the technical details, let's cover the basics. All our rendering endpoints live at:
1
https://api.canvelete.com/v1/render
You'll need your API key for every request. If you don't have one yet, grab it from your dashboard settings (opens in a new tab). You can also view your usage limits on the pricing page (opens in a new tab).
1
Authorization: Bearer YOUR_API_KEY
2
Content-Type: application/json
That's it! You're ready to start generating images.
The Main Event: Rendering Your Designs
Single Design Rendering
This is probably the endpoint you'll use most often. It takes one of your designs and turns it into a beautiful image with any dynamic data you provide.
POST /render/design/{designId}The {designId} is the unique identifier for your design. You can find this in your dashboard or in the URL when editing a design.
What You Can Control
Here's everything you can customize when rendering your design:
Required:
designId- The ID of the design you want to render (you'll find this in your dashboard)
Format Options:
format- Choose frompng,jpg,pdf,svg, orwebp(defaults topng)quality- How crisp you want it (1-100, we recommend 85 for most uses)width&height- Custom dimensions in pixels (optional, uses design defaults)scale- Make it bigger or smaller (0.1 to 5.0, where 1.0 is original size)
Dynamic Content:
dynamicData- This is where the magic happens! Pass in data to replace variables in your design
Advanced Options:
background- Override the background color (hex codes, rgb, rgba, or "transparent")dpi- For print-quality outputs (72 for web, 300 for print)
A Real Example
Let's say you have a social media template with variables for a user's name and profile picture. Here's how you'd render it:
1
{
2
400">"format": 400">"png",
3
400">"quality": 95,
4
400">"width": 1920,
5
400">"height": 1080,
6
400">"dynamicData": {
7
400">"title": 400">"Welcome to Canvelete",
8
400">"subtitle": 400">"Design automation made simple",
9
400">"userImage": 400">"https://example.com/user-avatar.jpg",
10
400">"brandColor": 400">"#FF7A00"
11
}
12
}
The dynamicData object is where you pass in the personalized content. Each key should match a variable in your design template (the ones wrapped in {{}} brackets).
What You Get Back
When your render is complete, we'll send you back all the details you need:
1
{
2
400">"success": true,
3
400">"data": {
4
400">"renderId": 400">"render_abc123def456",
5
400">"status": 400">"completed",
6
400">"downloadUrl": 400">"https://cdn.canvelete.com/renders/abc123def456.png",
7
400">"metadata": {
8
400">"format": 400">"png",
9
400">"width": 1920,
10
400">"height": 1080,
11
400">"fileSize": 245760,
12
400">"renderTime": 1.2,
13
400">"quality": 95
14
},
15
400">"expiresAt": 400">"2024-01-15T10:30:00Z"
16
}
17
}
The downloadUrl is your direct link to the generated image. These URLs are valid for 24 hours, so make sure to download or save the image to your own storage if you need it longer.
Batch Rendering: When You Need Many Images
Need to generate hundreds or thousands of images? Batch rendering is your friend. Instead of making individual API calls, you can queue up multiple renders in a single request. This is much faster and more efficient.
POST /render/batchParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
renders | array | Yes | Array of render configurations |
webhook | string | No | Webhook URL for completion notification |
priority | string | No | Processing priority (low, normal, high) |
Request Example
{
"renders": [
{
"designId": "design_123",
"format": "png",
"quality": 90,
"dynamicData": {
"name": "John Doe",
"title": "Software Engineer"
}
},
{
"designId": "design_123",
"format": "jpg",
"quality": 85,
"dynamicData": {
"name": "Jane Smith",
"title": "Product Manager"
}
}
],
"webhook": "https://your-app.com/webhooks/render-complete",
"priority": "normal"
}Response
{
"success": true,
"data": {
"batchId": "batch_xyz789abc123",
"status": "processing",
"totalRenders": 2,
"completedRenders": 0,
"estimatedCompletion": "2024-01-15T10:35:00Z",
"renders": [
{
"renderId": "render_001",
"status": "queued",
"designId": "design_123"
},
{
"renderId": "render_002",
"status": "queued",
"designId": "design_123"
}
]
}
}Get Render Status
Retrieves the current status and details of a render job.
GET /render/status/{renderId}Response
{
"success": true,
"data": {
"renderId": "render_abc123def456",
"status": "completed",
"progress": 100,
"downloadUrl": "https://cdn.canvelete.com/renders/abc123def456.png",
"metadata": {
"format": "png",
"width": 1920,
"height": 1080,
"fileSize": 245760,
"renderTime": 1.2
},
"createdAt": "2024-01-15T10:28:00Z",
"completedAt": "2024-01-15T10:29:12Z",
"expiresAt": "2024-01-15T10:30:00Z"
}
}Choosing the Right Format
We support several output formats, each with its own strengths. Here's how to pick the right one for your needs:
PNG - The Swiss Army knife of image formats. Great for web graphics, supports transparency, and works everywhere. This is our default and usually your best bet.
JPEG - Perfect for photos and images where file size matters more than transparency. Smaller files than PNG, but no transparent backgrounds.
WebP - The modern web format that's smaller than both PNG and JPEG while maintaining quality. Great if you're serving images on the web and want fast loading times.
PDF - When you need print-ready documents or vector-based outputs. Perfect for certificates, reports, or anything that needs to scale perfectly.
SVG - Scalable vector graphics that stay crisp at any size. Ideal for logos, icons, and simple graphics that need to work on everything from mobile screens to billboards.
Format-Specific Options
PNG Options
{
"format": "png",
"quality": 95,
"compression": "fast", // fast, balanced, best
"interlaced": false
}JPEG Options
{
"format": "jpg",
"quality": 85,
"progressive": true,
"optimizeHuffman": true
}PDF Options
{
"format": "pdf",
"pageSize": "A4", // A4, Letter, Legal, Custom
"orientation": "portrait", // portrait, landscape
"margins": {
"top": 20,
"right": 20,
"bottom": 20,
"left": 20
},
"embedFonts": true
}Getting the Quality Just Right
Quality is a balancing act between file size, render speed, and visual fidelity. Here's our guide to picking the right quality setting:
For web thumbnails (1-30): Fast and small files, perfect for preview images where speed matters more than perfection.
For standard web use (31-70): The sweet spot for most web applications. Good quality with reasonable file sizes and render times.
For high-quality displays (71-90): When visual quality is important but you still need reasonable performance. Great for hero images and marketing materials.
For print and production (91-100): Maximum quality for when every pixel counts. Larger files and slower renders, but perfect results.
Our Recommendations
Here are the settings we use for different scenarios:
{
"social_media_posts": { "quality": 85, "format": "png" },
"email_headers": { "quality": 75, "format": "jpg" },
"print_materials": { "quality": 95, "format": "pdf", "dpi": 300 },
"web_thumbnails": { "quality": 60, "format": "webp" }
}Dynamic Data Injection
Variable Types
The rendering engine supports various data types for dynamic content:
{
"dynamicData": {
"text": "String values for text elements",
"number": 42,
"boolean": true,
"color": "#FF7A00",
"image": "https://example.com/image.jpg",
"array": ["item1", "item2", "item3"],
"object": {
"nested": "values",
"supported": true
}
}
}Advanced Data Binding
Conditional Rendering
{
"dynamicData": {
"showBadge": true,
"badgeText": "NEW",
"userType": "premium"
}
}Image Transformations
{
"dynamicData": {
"profileImage": {
"url": "https://example.com/profile.jpg",
"crop": "circle",
"width": 200,
"height": 200
}
}
}Text Formatting
{
"dynamicData": {
"title": {
"text": "Dynamic Title",
"fontSize": 24,
"color": "#333333",
"fontWeight": "bold"
}
}
}Performance Optimization
Batch Processing Guidelines
- Optimal Batch Size: 10-50 renders per batch
- Priority Queuing: Use priority levels for time-sensitive renders
- Webhook Notifications: Implement webhooks for async processing
- Caching Strategy: Cache frequently used designs and assets
Performance Best Practices
Request Optimization
// Good: Batch similar renders
const batchRequest = {
renders: variations.map(data => ({
designId: "design_123",
format: "png",
quality: 80,
dynamicData: data
}))
};
// Avoid: Individual requests for similar renders
variations.forEach(data => {
// Don't do this for multiple similar renders
renderSingle(designId, data);
});Asset Optimization
- Pre-upload Assets: Upload images to Canvelete asset library
- Use CDN URLs: Reference assets via CDN for faster loading
- Optimize Images: Compress images before upload
- Font Subsetting: Use only required font characters
Caching Strategy
// Implement client-side caching
const cacheKey = `render_${designId}_${JSON.stringify(dynamicData)}`;
const cachedResult = cache.get(cacheKey);
if (cachedResult && !cachedResult.expired) {
return cachedResult.data;
}Rate Limiting
| Plan | Requests/Minute | Concurrent Renders | Batch Size |
|---|---|---|---|
| Free | 10 | 2 | 5 |
| Pro | 100 | 10 | 25 |
| Enterprise | 1000 | 50 | 100 |
Error Handling
Common Error Codes
| Code | Status | Description | Solution |
|---|---|---|---|
| 400 | Bad Request | Invalid parameters | Check request format |
| 401 | Unauthorized | Invalid API key | Verify authentication |
| 403 | Forbidden | Insufficient permissions | Check API key scope |
| 404 | Not Found | Design not found | Verify design ID |
| 422 | Unprocessable Entity | Invalid dynamic data | Validate data types |
| 429 | Too Many Requests | Rate limit exceeded | Implement backoff |
| 500 | Internal Server Error | Rendering failed | Contact support (opens in a new tab) |
Error Response Format
{
"success": false,
"error": {
"code": "INVALID_DYNAMIC_DATA",
"message": "Dynamic data validation failed",
"details": {
"field": "userImage",
"issue": "Invalid URL format",
"expected": "Valid HTTP/HTTPS URL"
},
"requestId": "req_abc123def456"
}
}Troubleshooting Guide
Common Issues
Render Timeout
Problem: Renders taking too long or timing out Solutions:
- Reduce image resolution or quality
- Optimize design complexity
- Use batch processing for multiple renders
- Check asset availability and size
Poor Quality Output
Problem: Rendered images appear blurry or pixelated Solutions:
- Increase quality setting (80-95 recommended)
- Use appropriate DPI for print (300 DPI)
- Ensure source assets are high resolution
- Check scale factor settings
Dynamic Data Not Applied
Problem: Template variables not being replaced Solutions:
- Verify variable names match design placeholders
- Check data type compatibility
- Ensure proper JSON formatting
- Validate nested object structure
Memory or Processing Errors
Problem: Renders failing due to resource constraints Solutions:
- Reduce batch size
- Lower output resolution
- Optimize design elements
- Use appropriate priority settings
Debug Mode
Enable debug mode for detailed rendering information:
{
"format": "png",
"quality": 85,
"debug": true,
"dynamicData": { ... }
}Debug response includes:
- Processing time breakdown
- Asset loading times
- Memory usage statistics
- Detailed error traces
Performance Monitoring
Monitor render performance with these metrics:
// Track render times
const startTime = Date.now();
const result = await renderDesign(config);
const renderTime = Date.now() - startTime;
// Log performance metrics
console.log({
renderId: result.renderId,
renderTime,
fileSize: result.metadata.fileSize,
quality: config.quality
});Support and Diagnostics
For persistent issues:
-
Collect Information:
- Request ID from error response
- Design ID and configuration
- Expected vs actual output
- Browser/environment details
-
Test Isolation:
- Try rendering without dynamic data
- Test with different formats/quality
- Use minimal design complexity
-
Contact Support:
- Include request ID and error details
- Provide sample design and data
- Describe expected behavior
SDK Examples
JavaScript/Node.js
import { CanveleteAPI } from '@canvelete/sdk';
const canvelete = new CanveleteAPI({
apiKey: 'your-api-key'
});
// Single render
const result = await canvelete.render.design('design_123', {
format: 'png',
quality: 90,
dynamicData: {
title: 'Hello World',
userImage: 'https://example.com/avatar.jpg'
}
});
// Batch render
const batchResult = await canvelete.render.batch([
{
designId: 'design_123',
format: 'png',
dynamicData: { name: 'John' }
},
{
designId: 'design_123',
format: 'jpg',
dynamicData: { name: 'Jane' }
}
]);Python
from canvelete import CanveleteAPI
client = CanveleteAPI(api_key='your-api-key')
# Single render
result = client.render.design('design_123', {
'format': 'png',
'quality': 90,
'dynamic_data': {
'title': 'Hello World',
'user_image': 'https://example.com/avatar.jpg'
}
})
# Check status
status = client.render.get_status(result['data']['render_id'])cURL
# Single render
curl -X POST "https://api.canvelete.com/v1/render/design/design_123" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"format": "png",
"quality": 90,
"dynamicData": {
"title": "Hello World"
}
}'
# Get render status
curl -X GET "https://api.canvelete.com/v1/render/status/render_abc123" \
-H "Authorization: Bearer YOUR_API_KEY"Webhooks
Configure webhooks to receive notifications when renders complete:
{
"event": "render.completed",
"data": {
"renderId": "render_abc123def456",
"status": "completed",
"downloadUrl": "https://cdn.canvelete.com/renders/abc123def456.png",
"metadata": {
"renderTime": 1.2,
"fileSize": 245760
}
},
"timestamp": "2024-01-15T10:29:12Z"
}For webhook setup and security, see the Webhooks documentation.