PICTIFY
For Developers

Bulk image generation,
done right.

Render thousands of images from a CSV, spreadsheet, or JSON batch. Async jobs, webhooks on completion, parallelized renders — all from one template.

"We need 10,000 certificates by Friday." "Every user gets a personalized year-in-review card." "Re-render OG images for every archived blog post after the rebrand." All the same problem: one template × N rows of data = N images, and you'd like to finish before the weekend.

Bulk image generation is the batch-rendering primitive for this class of workload. Submit a batch, get a webhook when it's done, deliver the URLs. No N individual API calls, no manual rate-limit management, no orchestrator to build.

When bulk rendering is the right tool

Campaign launches

New feature ships; every user gets a personalized announcement graphic. 40,000 users, 40,000 images. Render the batch, email the URLs.

Catalog backfills

Existing e-commerce catalog that never had OG images per product. One batch POST, every product has a rendered card. Store the URLs on the product records.

Certificate runs

Course cohort completes; every graduate gets a certificate. The batch lists all 500 graduates with their names and dates. Output is 500 PDF + 500 PNG ready to email.

Monthly reports

End of month; render a dashboard summary image per customer from their usage data. Batch of N customers, one webhook, newsletter pipeline picks up the URLs.

Batch render example

batch-render.ts
// Render a certificate for every graduate in one request
const graduates = await db.graduates.listByCohort(cohortId);

const response = await fetch('https://api.pictify.io/template/tpl_certificate/batch', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.PICTIFY_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    variables: graduates.map(g => ({
      recipient_name: g.full_name,
      course_name: g.course,
      completion_date: g.completed_at,
      certificate_id: g.id
    })),
    webhookUrl: 'https://yourapp.com/hooks/batch-complete'
  })
});

const { jobId } = await response.json();
// Webhook fires when all N certificates render. Payload includes URLs.

Performance expectations

  • 100 images — typically under 30 seconds
  • 1,000 images — typically 2–4 minutes
  • 10,000 images — typically 15–25 minutes
  • 50,000 images — typically 1.5–2 hours

Actual time depends on template complexity and external asset load (external images in the template add latency). Webhooks let you kick off a batch, free the calling process, and pick up delivery when the job finishes — no need to hold connections or manage retries yourself.

Frequently asked questions

How do I generate images in bulk from a CSV? +

Two paths. If you own the backend: parse the CSV, POST each row as a variables object to the render API (or batch them). If you want zero code: use Pictify's Google Sheets integration — connect the sheet, map columns to template variables, trigger a batch render. Either way produces CDN-cached URLs you can reference in your email, CMS, or storefront.

What's the difference between sending 1,000 individual renders vs one batch request? +

Performance and cost. The batch endpoint parallelizes internally — 1,000 images render in roughly the time of 100 individual calls. It also handles the webhook lifecycle so your code doesn't need to manage N in-flight requests. For workloads over ~100 images, always use batch.

How large a batch can I submit at once? +

Tested up to 50,000 rows in a single request. Larger batches work but get queued; if your workload is over ~25K at once, split into chunks. The batch endpoint returns a job ID; poll for status or register a webhook.

Can I generate bulk images from a live data source instead of a static CSV? +

Yes — use live data bindings. Define the template once with a binding to an HTTP endpoint or webhook; trigger a batch render whenever the source updates. Pictify fetches current data per render, so your images always reflect current state. Live bindings are unique to Pictify; other template APIs require you to pass static variables every call.

What happens if one image in the batch fails? +

The batch continues; failures are reported in the webhook payload with per-row error details. You can retry just the failed rows with a second batch call. No "whole batch fails because one row has a bad URL" situations.

How do I handle image delivery at the end of a batch? +

Webhook fires when the batch completes. Payload includes an array of render results (URL + metadata per row). Common patterns: email the URLs to users, update CRM records with image fields, upload to S3 / Cloudinary for your own delivery pipeline.

Bulk Image Generation

One template. N rows. One webhook.

Real expression engine

{{ price * 0.9 | currency }} is a first-class template feature — not a string you pre-format in your backend. Conditionals, filters, nested lookups, all built in.

Live data bindings

Templates connect to HTTP endpoints, webhooks, or static JSON. Images update when data updates. Nothing else in the category ships this.

API + no-code, same product

Designers build templates in a visual canvas. Engineers call one endpoint. No hand-off, no context switch, no rebuild.

A/B experiments on images

Ship variants of a template, track impressions and conversions per variant, declare a winner — all from the same API that renders the image.

One API, many outputs

PNG, JPEG, WebP, multi-page PDF, GIF. Same template, different fileExtension. No separate service for each format.

Agentic AI copilot

"Make a dark-mode variant," "resize this for Instagram Story," "generate five backgrounds." The copilot edits templates step by step, not as a single-shot generator.

Related solutions