# 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.

- **URL**: https://orshot.com/help/use-approvals-from-the-api

---

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:

```json
{
  "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"
}
```

1. Branch on `code`: `template_not_approved`, `output_not_approved`, `edited_since_approval` or `condition_violated`.
2. Show `message` as it is. It's written for people, and names the flow and the stage.
3. 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](https://orshot.com/docs/error-reference#approval-errors).

## AI agents

An agent connected through the [Orshot MCP server](https://orshot.com/docs/integrations/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

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.

```js
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](https://orshot.com/docs/api-reference/approvals-overview#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](https://orshot.com/help/approval-flows-after-a-downgrade). |

## Related

- **[Approvals API overview](https://orshot.com/docs/api-reference/approvals-overview)**: Authentication, access levels and retries
- **[Use Orshot with AI agents](https://orshot.com/help/use-orshot-with-ai-agents)**: Connect Claude, ChatGPT and other agents