Automated Business Metrics Video, One per Client
Render an automated business metrics video for every client from the numbers your reporting job already computes, with the same look each month.

An automated business metrics video comes from numbers you already have. Your reporting job closes the month, sends four figures per client to one API request, and gets back a 34-second 16:9 recap. Each figure lands on its own frame with the change against last month. Set up one project with your labels, and every client gets a video on the 1st.
The finished video
This guide renders Monthly Performance Recap, a 34-second 1920x1080 video in seven scenes: a cover, four figure scenes with a value, a label and a change chip, a ledger with all four metrics, and a close.
For internal reporting, the Quarterly Business Review template renders one 34-second review per department against plan. Its definition lines are fixed text too, so step 2 applies to it as well.
What you need
- A Renderly API key. Create one in the dashboard under Settings → API keys.
- A reporting job that already computes each client's monthly figures: a SQL query, a spreadsheet or your analytics export.
- The client's logo mark at a URL that serves the image file directly.
Step 1 - Decide what the video adds to the report
Dashboards track the numbers live, and a client who wants to explore the data should keep one. AI video report tools gather the campaign data and interpret it for you.
A template does a narrower job. Your job computes the figures, and the video states them. Nothing reads, rounds or rewrites a number. Every client gets the same type, pacing and close, so 80 accounts get 80 videos that look like one firm made them, at a cost fixed by the length.
Step 2 - Make the fixed labels yours in a project
The 19 fields do not cover every word on screen. The sample's month, agency and data sources are fixed text in the template:
- the comparison month:
VS JUNEon each figure andALL FIGURES VS JUNEon the ledger - the chart labels:
JUNE · DAILYandJULY · DAILY(CUMULATIVEon the fourth) - the agency:
PREPARED BY FIELDMARKon the cover andFIELDMARKon the close - the window and sources:
MEASURED JUL 1-31, theSOURCE:lines and one definition line per metric
Render the template as it ships and a September recap still says June, July
and Fieldmark. Fix this once. Click Use this template
on the template page to clone it into a
project. In the editor, type your agency name and your definitions straight
into their layers. For text that changes each month, give the layer a name,
such as comparison_label, and tick Dynamic. Layers that show the same
text can share one name, so one value fills all of them. The fourth chart says
CUMULATIVE, so give its labels their own names.
Step 3 - Map each client's month to the template fields
| Fields | What goes in them |
|---|---|
client_name, client_mark, client_logo | The name on the cover, a short wordmark and a logo URL |
period_label, client_period_line | The month, and the client and month as one line |
ledger_title, period_closed_line | The ledger heading and the closing line |
metric_1_value to metric_4_value | Each figure, already formatted |
metric_1_label to metric_4_label | What each figure measures |
metric_1_delta to metric_4_delta | The change, with its own arrow |
Each metric field fills two places, its own scene and its ledger column, so one
value is enough. Add the names you created in step 2. Send every field. An omitted one keeps the sample value, so a
missing metric_4_value shows the template's $312,400 on your client.
Step 4 - Fit each figure to its slot
The figures are set very large, and the four slots differ in width. The
variables endpoint, GET /api/v1/projects/{projectId}/variables, reports a maxCharacters for each field. The first and third values have room
for about 5 characters, the second for about 8 and the fourth for about 11. Put
the longest figure, usually revenue, in slot 4, and a short count in slots 1
and 3. Write "$1.2M" rather than "$1,204,310".
A value that is too long does not fail. The tail is hidden and the render still
succeeds. Preview a few clients first. Previews take the same body, cost
nothing, and return a previewUrl and a warnings array:
curl -X POST https://renderly.video/api/v1/previews \
-H "Authorization: Bearer $RENDERLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "projectId": "cmgb7x2k40001la08n3q9v6rd", "replacements": { "metric_1_value": "12,480" } }'A value that will clip returns TEXT_MAY_CLIP. It is an estimate from average
character width, so open the previewUrl for every client it flags.
Step 5 - Render one recap per client on the 1st
curl -X POST https://renderly.video/api/v1/renders \
-H "Authorization: Bearer $RENDERLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"projectId": "cmgb7x2k40001la08n3q9v6rd",
"replacements": {
"client_name": "Northgate\nPhysiotherapy",
"client_mark": "NORTHGATE",
"client_logo": "https://assets.example.com/northgate/mark.png",
"period_label": "SEPTEMBER 2026",
"client_period_line": "NORTHGATE PHYSIOTHERAPY · SEPTEMBER 2026",
"ledger_title": "September, in full",
"period_closed_line": "SEPTEMBER 2026 · CLOSED",
"metric_1_value": "386",
"metric_1_label": "NEW PATIENT ENQUIRIES",
"metric_1_delta": "▲ 12%",
"metric_2_value": "$21.10",
"metric_2_label": "COST PER ENQUIRY",
"metric_2_delta": "▼ 8%",
"metric_3_value": "142",
"metric_3_label": "FIRST VISITS BOOKED",
"metric_3_delta": "▲ 9%",
"metric_4_value": "$198,600",
"metric_4_label": "REVENUE ATTRIBUTED",
"metric_4_delta": "▲ 6%",
"comparison_label": "VS AUGUST",
"prior_chart_label": "AUGUST · DAILY",
"current_chart_label": "SEPTEMBER · DAILY",
"measured_window": "MEASURED SEP 1-30"
}
}'Use your own project id, from the editor URL
(/dashboard/projects/{projectId}/edit), and your own logo URL. The last four
keys are the names this example gave in step 2. The response returns a jobId and
creditsUsed: 1 immediately. Run the request from the same job that closes
the month, one client per request, with the loop from the
CSV guide. Requests are limited per minute
by plan: 120 on Creator and 300 on Business. There are no idempotency keys, so
a retry after a timeout can render and charge for the same client twice. Check
Dashboard → Renders before you retry.
Step 6 - Send the video with the report
Keep your own map from client to jobId as each POST returns. Register one webhook with
POST /api/v1/webhooks for render.completed, look the client up by jobId,
and attach the outputUrl to that client's report email. The
webhooks guide covers verifying
the signature.
If a figure is corrected after the send, fix it in your data and render that client again. The new video matches the old one except for the changed value.
What this costs at scale
Renderly bills 1 credit per minute of 1080p output, rounded up to the nearest half credit. The 34-second recap rounds up to 1 credit, and so does the 34-second quarterly review.
| Clients | Credits per month | Plan | Cost |
|---|---|---|---|
| 100 | 100 | Creator, $29/mo (200 credits) | included |
| 1,000 | 1,000 | Business, $99/mo (1,000 credits) | included |
Re-rendering one corrected client costs 1 credit.
Where to go next
The case for one fixed look over a generator that changes it every run is in template-based video vs AI-generated video. If the monthly figures live in a spreadsheet, the Google Sheets guide sends each row as one render.
Frequently asked
Does the template calculate or format the numbers?
Are the line charts drawn from my data?
What happens when a value is too long for its slot?
Can a decline look different from a gain?
Is there a version for internal reviews?
Related guides
Google Sheets to Video: Automate Video Creation from a Sheet
Turn spreadsheet rows into finished videos. Connect a Google Sheet to the Renderly API with Apps Script, map columns to variables, and render every row.
Airtable to Video: Automate Video Creation from a Base
Turn Airtable records into finished videos automatically. Connect a base to the Renderly API, map fields to template variables, and render every row without opening an editor.
Bulk Video from CSV: Generate One Video per Row
Turn a CSV export into finished videos. Map headers to template variables, send one render request per row from a resumable script, and collect every result.