> ## Documentation Index
> Fetch the complete documentation index at: https://omni.fireflo.au/llms.txt
> Use this file to discover all available pages before exploring further.

# POST /v1/agents/plans/{plan_id}/reject

> Reject a plan waiting for approval, and tell the agent why.

Rejects a plan waiting for approval — the whole plan, or, in step-by-step mode, a plan with a step waiting. Nothing more of it runs. The agent reads your note the next time it plans for this contact.

<Note>Needs the `agents.plans:write` scope.</Note>

## Path parameters

| Field | Type | Required | Notes |
| :- | :- | :- | :- |
| `plan_id` | integer | Yes | The plan's id. |

## Body

| Field | Type | Required | Notes |
| :- | :- | :- | :- |
| `note` | string | No | Why, for the agent. Up to 1,000 characters. |

## Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.fireflo.au/v1/agents/plans/4812/reject" \
    -H "Authorization: Bearer $OMNI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "note": "No discount on inverters this month — offer free installation instead."
    }'
  ```

  ```python Python theme={null}
  import os

  import requests

  response = requests.post(
      "https://api.fireflo.au/v1/agents/plans/4812/reject",
      headers={"Authorization": f"Bearer {os.environ['OMNI_API_KEY']}"},
      json={
          "note": "No discount on inverters this month — offer free installation instead."
      },
  )
  print(response.status_code, response.json())
  ```

  ```javascript Node theme={null}
  const response = await fetch("https://api.fireflo.au/v1/agents/plans/4812/reject", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.OMNI_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "note": "No discount on inverters this month — offer free installation instead."
    }),
  });
  console.log(response.status, await response.json());
  ```
</CodeGroup>

## Response

`200 OK` — the plan, now `rejected`.

```json theme={null}
{
  "id": 4812,
  "agent": {
    "id": 7,
    "name": "Arjun",
    "role": "sales"
  },
  "scope": "contact",
  "campaign_id": null,
  "contact": {
    "id": 90417,
    "uuid": "3f6b2a1e-8c4d-4e2a-9b7f-5d1c0e8a9f42",
    "name": "Neha Arora",
    "msisdn": "+919876500102"
  },
  "deal": {
    "id": 3318,
    "title": "Arora Traders — 40 inverters",
    "stage": "Quoted"
  },
  "pipeline": {
    "id": 2,
    "name": "B2B sales"
  },
  "trigger": "inbound_message",
  "trigger_excerpt": "Can you do ₹6,200 per unit if we take 40?",
  "goal": "Answer Neha's price question and keep the quote moving",
  "rationale": "She asked for a lower unit price on a large order. The playbook allows up to 5% off above 25 units, so offer ₹6,350 and note it on the deal.",
  "status": "rejected",
  "approval_mode": "plan",
  "approval_reasons": [
    "Send a message needs approval"
  ],
  "created": "2026-10-06T10:14:22+05:30",
  "expires_at": "2026-10-07T10:14:31+05:30",
  "next_run_at": null,
  "tokens": 2310,
  "model": "gpt-4o-mini",
  "decided_by": null,
  "decision_note": "No discount on inverters this month — offer free installation instead.",
  "last_error": null,
  "steps": [
    {
      "id": 20931,
      "order": 1,
      "action": "send_message",
      "title": "Send WhatsApp message",
      "body": "Hi Neha, for 40 units we can do ₹6,350 each, delivered to Ludhiana within 10 days. Shall I update the quote?",
      "detail": "WhatsApp",
      "reason": "Answer the price question while she is online.",
      "run_at": "2026-10-06T10:14:31+05:30",
      "requires_approval": true,
      "status": "rejected",
      "result": null,
      "editable": [
        "body"
      ],
      "params": {
        "channel": "whatsapp",
        "body": "Hi Neha, for 40 units we can do ₹6,350 each, delivered to Ludhiana within 10 days. Shall I update the quote?",
        "channel_locked": true
      }
    },
    {
      "id": 20932,
      "order": 2,
      "action": "add_note",
      "title": "Add note",
      "body": "Offered ₹6,350/unit for 40 units (5% off list).",
      "detail": null,
      "reason": "Keep the team aware of the offer.",
      "run_at": "2026-10-06T10:14:31+05:30",
      "requires_approval": false,
      "status": "rejected",
      "result": null,
      "editable": [
        "body"
      ],
      "params": {
        "body": "Offered ₹6,350/unit for 40 units (5% off list)."
      }
    },
    {
      "id": 20933,
      "order": 3,
      "action": "follow_up",
      "title": "Follow up",
      "body": null,
      "detail": "Check whether Neha accepts the revised price",
      "reason": "No reply by tomorrow means the quote needs a nudge.",
      "run_at": "2026-10-07T11:00:00+05:30",
      "requires_approval": false,
      "status": "rejected",
      "result": null,
      "editable": [],
      "params": {
        "goal": "Check whether Neha accepts the revised price"
      }
    }
  ],
  "audience": null,
  "story_id": null
}
```

## Errors

Every refusal is `{"error": {"code", "message", "field"}}`; `field` is there when one input is at fault.

| Status | Error code | When |
| :- | :- | :- |
| 400 | `invalid_request` | `note` isn't text or is over 1,000 characters (`field` is `note`). |
| 404 | `not_found` | No plan of this account's has that id. |
| 409 | `invalid_state` | The plan isn't waiting for approval. |
| 404 | `module_off` | The account doesn't have AI agents on: they aren't in its plan, or are switched off for it. |
| 403 | `scope_missing` | The key doesn't have the `agents.plans:write` scope. |

Any request can also be refused for its key, its account or its rate (`key_required`, `invalid_key`, `account_suspended`, `plan_excludes_api`, `address_not_allowed`, `rate_limited`); see [the overview](/api-reference/overview).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.