How to use approvals from the API or an agent
Blocked renders return a plain reason to any API client or agent. The Approvals API adds, moves and approves templates from your own code.
Published Sep 29, 2026
Approvals reach your code in two ways. Every API client and agent meets them when a render is blocked, on any plan with approval flows. The Approvals API goes further and lets your code add, move and approve templates.
Handle a blocked render#
When a template's flow needs approval for automation, a render from the REST API, an SDK, n8n, Make, Zapier or the Orshot MCP server is refused with a 403 until the template is approved:
{
"error": "This template is waiting for approval in 'Brand and legal' and can't be rendered through the API yet.",
"code": "template_not_approved",
"message": "This template is waiting for approval in 'Brand and legal' and can't be rendered through the API yet.",
"blockers": [
{
"flow": { "slug": "brand-and-legal", "name": "Brand and legal" },
"stage": { "slug": "brand-review", "name": "Brand review", "category": "review" },
"reason": "not_in_render_stage",
"waitingOn": ["Priya Shah"],
"renderStage": { "slug": "approved-for-automation", "name": "Automation approved" }
}
],
"helpUrl": "https://orshot.com/docs/error-reference#template-not-approved"
}- Branch on
code:template_not_approved,output_not_approved,edited_since_approvalorcondition_violated. - Show
messageas it is. It's written for people, and names the flow and the stage. - Send the render again once it's approved. Nothing was rendered or queued, and no credits were used.
Every code is explained in Approval errors.
AI agents#
An agent connected through the Orshot MCP server acts as the person who connected it, with their access. When it renders a template that's waiting for approval, it gets the message above and can tell you the stage and who can approve it. When it tries to change a template in a locked stage, it gets stage_locked.
The Approvals API#
Enterprise plans and first-party apps
The Approvals API is available on Enterprise plans, or through first-party apps (the Orshot app and the Orshot MCP server).
It does what the Approvals page does, from your own code. A typical automation adds new templates to a flow, submits them for review, and checks they're approved before it renders.
- 1
Ask for the access levels you need
read to check status, move to add and move templates, decide to approve, manage to change flows. Levels don't include each other.
- 2
Add the template to a flow
Find the flow's slug with List Approval Flows, then call Add a Template to an Approval Flow with its
templateId. - 3
Submit it for review
Call Move a Template to Another Stage with
toStage: "brand-review"and therevisionyou got back. - 4
Check before you render
Call Get a Template's Approval Status. Render when
canRender.image(orpdf,video) istrue.
const headers = { Authorization: "Bearer <ORSHOT_API_KEY>" };
const { status } = await fetch(
"https://api.orshot.com/v1/studio/templates/101/approval",
{ headers },
).then((r) => r.json());
if (status.canRender.image) {
await fetch("https://api.orshot.com/v1/studio/render", {
method: "POST",
headers: { ...headers, "Content-Type": "application/json" },
body: JSON.stringify({
templateId: 101,
modifications: { headline: "Summer sale" },
response: { type: "url", format: "png" },
}),
});
} else {
console.log(status.blockers[0]); // which stage, and who it waits on
}An API key acts as the workspace, so its moves show in the activity history "via API". An OAuth token acts as the person who connected your app, with their own access in each flow.
To act for one person on your team with an API key, send their user id in the X-Orshot-User-Id header. The call then needs both the key's access and theirs, their own inbox and notifications answer, and changes read as "Priya Shah, via API key". Approving always comes from the person. See acting for a team member.
Common problems#
| You see | Why, and what to do |
|---|---|
403 enterprise_api_required | The Approvals API isn't on for your workspace, or not at this level. required names the level. |
409 state_conflict: "Someone else moved this template first." | Read current, check the move still makes sense, and send it again with the new revision. |
409 stale_review when approving | The design changed. Send the new currentVersion as reviewedVersion after checking it. |
403 permission_denied on approve | The person behind the token isn't an approver in that stage. The message names who is. With the code approval.decision_person_required, an API key sent X-Orshot-User-Id: approvals come from the person, through their OAuth token or the Orshot app. |
403 permission_denied with the code approval.member_header_not_member | X-Orshot-User-Id names a reviewer, someone who left, or someone outside the workspace. It must be an owner, admin or member. |
403 permission_denied: "Reviewers can't move templates between stages. They approve or request changes." | The token belongs to a reviewer. Reviewers only comment, approve and request changes. |
403 flow_limit_reached with the code approval.flow.over_plan_limit | The flow is over your plan's limit after a downgrade, so it can't be changed. Archive a flow or upgrade. See what happens after a downgrade. |
Related#
More in Approval flows
Ready to automate?
Start rendering images, PDFs and videos from your templates in under 2 minutes. Free plan, no credit card.
Get your API key- Image, PDF and video generation via API
- Visual editor with AI and smart layouts
- Zapier, Make, MCP and 50+ integrations
- White-label embed for your own app
- 100 free credits a month, no credit card required