Schedule your Make scenario or Power Automate flow to pull this week's numbers, send them as JSON to thirds.ai, and get back a branded PDF or image built from a saved design. There is no published Make app or Power Automate connector for thirds.ai, so each tool reaches the API through its own generic HTTP action. Each successful file costs one credit, and a verified free account starts with 50 credits a month with no card.
This guide adds a weekly schedule trigger and the exact HTTP steps for both tools. The API workflow guide covers the same request for n8n, Zapier, and other workflow tools.
Connect Make or Power Automate to the API
Both tools call the same thirds.ai endpoint, so the setup only differs in where each one keeps the schedule and the request. Create a key on the API keys page and send it as Authorization: Bearer YOUR_API_KEY. Keep the key in the tool's own connection or secret store, never typed into a step you export or share.
Make: HTTP module
- Add a schedule to the scenario. Click the clock icon and set it to run every Monday morning.
- Add a module that reads this week's numbers from your CRM, spreadsheet, or database.
- Add an HTTP > Make a request module:
- URL:
https://thirds.ai/v1/pdffor a document, orhttps://thirds.ai/v1/imagefor a picture. - Method:
POST. - Headers:
Authorization: Bearer YOUR_API_KEY,Content-Type: application/json, andIdempotency-Keyset to something that changes only once a week, such asweekly-report-{{formatDate(now; "YYYY-WW")}}. A key like this keeps a retried scenario run from making a second file. - Body type: Raw. Content type: JSON (
application/json). - Request content: the JSON body in Fill a saved report design below, with your own values mapped in from the previous module.
- URL:
Power Automate: HTTP action
- Add a Recurrence trigger and set it to run every Monday morning.
- Add an action that reads this week's numbers from your system of record.
- Add an HTTP action:
- Method:
POST. - URI:
https://thirds.ai/v1/pdforhttps://thirds.ai/v1/image. - Headers:
AuthorizationasBearer @{parameters('ThirdsApiKey')},Content-Typeasapplication/json, andIdempotency-Keyas something likeweekly-report-@{utcNow('yyyy-MM-dd')}. - Body: the JSON body below, with your own values in place of the sample ones.
- Method:
Fill a saved report design
Two verified gallery designs fit a weekly update. Open either one, choose Open in editor to save your own copy, and read its template ID from your templates list.
One metric and a next step
The Campaign report template design leads with one number, a short note on what moved it, and one action for next week. Every field is optional, so you can send only the ones you have.

| Field | Holds |
|---|---|
period | The week or reporting range |
title, summary | The report heading and a short summary |
metric_label, metric, metric_note | The headline number, its label, and why it moved |
next_step | The one thing to do next |
footer | Who prepared the report |
primary_colour | Your brand colour for the metric card |
curl --fail-with-body --silent --show-error https://thirds.ai/v1/pdf \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: weekly-report-2026-38' \
--data '{
"template_id": "tpl_00000000000000000000000000000000",
"version": 1,
"data": {
"period": "Week 38, 2026",
"title": "Revenue pipeline expanded across inbound tiers.",
"summary": "Weekly inbound pipeline and conversion summary for the RevOps team.",
"metric_label": "Weekly conversion rate",
"metric": "+31%",
"metric_note": "Refined landing copy and a faster lead response time.",
"next_step": "Review mid-funnel drop-off with the outbound team on Tuesday.",
"footer": "Prepared by RevOps",
"primary_colour": "#E2A73A"
}
}'const response = await fetch("https://thirds.ai/v1/pdf", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
"Idempotency-Key": "weekly-report-2026-38"
},
body: JSON.stringify({
"template_id": "tpl_00000000000000000000000000000000",
"version": 1,
"data": {
"period": "Week 38, 2026",
"title": "Revenue pipeline expanded across inbound tiers.",
"summary": "Weekly inbound pipeline and conversion summary for the RevOps team.",
"metric_label": "Weekly conversion rate",
"metric": "+31%",
"metric_note": "Refined landing copy and a faster lead response time.",
"next_step": "Review mid-funnel drop-off with the outbound team on Tuesday.",
"footer": "Prepared by RevOps",
"primary_colour": "#E2A73A"
}
}),
redirect: "error",
signal: AbortSignal.timeout(30000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}; Retry-After: ${response.headers.get("retry-after") ?? "none"}`);
console.log(await response.text());import json
from urllib.error import HTTPError
from urllib.request import HTTPRedirectHandler, Request, build_opener
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
request = Request("https://thirds.ai/v1/pdf",
method="POST",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
"Idempotency-Key": "weekly-report-2026-38"
},
data=json.dumps({
"template_id": "tpl_00000000000000000000000000000000",
"version": 1,
"data": {
"period": "Week 38, 2026",
"title": "Revenue pipeline expanded across inbound tiers.",
"summary": "Weekly inbound pipeline and conversion summary for the RevOps team.",
"metric_label": "Weekly conversion rate",
"metric": "+31%",
"metric_note": "Refined landing copy and a faster lead response time.",
"next_step": "Review mid-funnel drop-off with the outbound team on Tuesday.",
"footer": "Prepared by RevOps",
"primary_colour": "#E2A73A"
}
}).encode("utf-8"),
)
try:
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(response.read().decode("utf-8"))
except HTTPError as error:
retry = error.headers.get("Retry-After", "none")
raise RuntimeError(f"HTTP {error.code}; Retry-After: {retry}") from NoneRevenue, clients, and growth in one page
The Monthly report template design fits a fuller update with a growth badge, a revenue card, a new-clients card, and a short plan for next period. Its schema requires every field below and rejects extra ones.

| Field | Holds |
|---|---|
business_name | The team or company issuing the report |
period | The reporting range |
revenue | The headline revenue figure, already formatted |
clients | The new-clients count |
growth | The growth figure for the badge |
highlights | What went well, in a sentence or two |
next_steps | The plan for next period |
Send this body to the same /v1/pdf request, with template_id and version set to your saved copy of Monthly report.
Read the job and download the file
thirds.ai returns 200 with a terminal status when the file is ready inside the request's short wait, or 202 while the job is still queued or running. A 200 response can still carry succeeded, failed, or cancelled, so read status either way.
- If
statusissucceeded, copydownload.urlfrom the response. It is a relative path, so addhttps://thirds.aiin front of it before you use it. - If the response is
202, pollGET /v1/pdf/{id}(or/v1/image/{id}) with a short delay under your own timeout. Stop atsucceeded,failed, orcancelled. - The signed download link lasts 15 minutes, and the file itself stays available for 30 days. Add a step after the download to save it straight to SharePoint, Google Drive, or S3, or to send it as an email or Teams attachment, so nobody has to revisit the run later.
curl --fail-with-body --silent --show-error \
https://thirds.ai/v1/pdf/pdf_00000000000000000000000000000000 \
-H 'Authorization: Bearer YOUR_API_KEY'const response = await fetch("https://thirds.ai/v1/pdf/pdf_00000000000000000000000000000000", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_KEY"
},
redirect: "error",
signal: AbortSignal.timeout(30000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}; Retry-After: ${response.headers.get("retry-after") ?? "none"}`);
console.log(await response.text());import json
from urllib.error import HTTPError
from urllib.request import HTTPRedirectHandler, Request, build_opener
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
request = Request("https://thirds.ai/v1/pdf/pdf_00000000000000000000000000000000",
method="GET",
headers={
"Authorization": "Bearer YOUR_API_KEY"
},
)
try:
with build_opener(NoRedirect()).open(request, timeout=30) as response:
print(response.read().decode("utf-8"))
except HTTPError as error:
retry = error.headers.get("Retry-After", "none")
raise RuntimeError(f"HTTP {error.code}; Retry-After: {retry}") from NoneSave the job ID next to the week it covers in your own workflow history. If a run times out or a step fails after the create request, run the same step again with the same Idempotency-Key and body. You get the same job back, and you're never billed twice for one week's report. Read retry and download recovery for the full contract.
Sending the same report to many clients each week? Batches fills one saved design from a CSV of rows and returns every file in one ZIP, so your scheduled flow only needs to build one file and one row per client.
What this costs each week
One finished file costs one credit, and a failed file costs nothing. Four weekly reports sent to ten clients make 40 files a month, so that run spends exactly 40 credits. A verified free account starts with 50 credits a month with no card, and Starter adds 2,500 credits a month for $29 billed monthly or $290 billed yearly as your reporting volume grows.
Fix the common failures
| What you see | What it means and what to do |
|---|---|
400 template_data_invalid | The data fails the saved design's schema. Fix the listed fields and send the step again. |
template_missing_data | The saved design reads a field the request didn't include. Send every required field. |
402 insufficient_credits | Add credits or wait for next month's grant, then retry with the same key. |
409 idempotency_conflict | The same key was used with different data. Give this week's run its own key. |
429 rate_limited | Wait for Retry-After, then retry with the same key. |
Job category renderer_failure | Internal recovery ended. Start a new job with a retry limit, or contact support with the job ID. |
Read next
- Make reports, invoices, and ads from data covers the full request and response contract this recipe reuses.
- Use templates with your data explains fields, schemas, and saved versions.
- Make a CSV batch sends one saved design to many rows in a single run.
- The reports page shows the full workflow from design to a finished file.
- Register a webhook instead of polling, and let thirds.ai tell your flow when a report is ready.
Sign in to copy a report template and send your first request with the free monthly credits.



