---
title: Preview and Submit Approvals
slug: preview-and-submit-approvals
docTags: 
createdAt: 2026-09-04T04:17:01.816Z
---

This guide covers the read-then-submit half of the Approvals API: finding the applicable process, previewing the approval path, submitting a record, and recalling it if it needs to change.

## List Approval Processes

Returns the approval processes configured for an object, in the order the approval engine evaluates them.

```javascript
GET /cpq/approval-processes
```

| Parameter    | Type    | Description                                                                               |
| ------------ | ------- | ----------------------------------------------------------------------------------------- |
| `objectType` | string  | Object to list processes for, for example `Quote`. Required unless `recordId` is supplied |
| `recordId`   | string  | Derives the object from a record and returns only processes applicable to that record     |
| `activeOnly` | boolean | Return only active processes                                                              |

```bash
curl -X GET 'https://api.nue.io/cpq/approval-processes?objectType=Quote&activeOnly=true' \
  -H 'nue-api-key: YOUR_API_KEY'
```

```json
{
  "status": "SUCCESS",
  "data": {
    "objectType": "Quote",
    "processes": [
      {
        "processName": "Standard Discount Approval",
        "objectType": "Quote",
        "versionNumber": 3,
        "isActive": true,
        "processOrder": 1,
        "appliesWhen": "Discount greater than 15%",
        "description": "Routes discounted quotes to the deal desk and above"
      }
    ]
  },
  "warnings": [],
  "errors": []
}
```

Supply `recordId` instead of `objectType` when you want only the processes that actually apply to one record.

## Preview the Approval Path

Returns the routing a record would follow if it were submitted right now. **Nothing is written** — you can call this as often as you like.

```javascript
POST /cpq/approvals:preview
```

| Field         | Type   | Description                                           |
| ------------- | ------ | ----------------------------------------------------- |
| `recordId`    | string | **Required.** The record to preview                   |
| `processName` | string | Omit to let the engine resolve the applicable process |

```bash
curl -X POST 'https://api.nue.io/cpq/approvals:preview' \
  -H 'nue-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{ "recordId": "0Q0Kb000000XyZaKAK" }'
```

```json
{
  "status": "SUCCESS",
  "data": {
    "recordId": "0Q0Kb000000XyZaKAK",
    "requiresApproval": true,
    "resolvedProcessName": "Standard Discount Approval",
    "paths": [
      {
        "pathId": "a0RKb000000TxAbMAK",
        "pathName": "Discount over 15%",
        "willTrigger": true,
        "dependsOnPathId": null,
        "steps": [
          {
            "stepId": "a0SKb000000UvBcMAK",
            "stepName": "Deal Desk",
            "stepStatus": null,
            "triggerReason": "Discount is 22%, threshold is 15%",
            "approvalReason": "Discount approved by deal desk",
            "resolveOn": "AllApprovers",
            "numberOfApprovers": 1,
            "dependsOnStepId": null,
            "isRemembered": false,
            "approvers": [
              {
                "approverType": "User",
                "userId": "005Kb000000WxYzIAK",
                "name": "Dana Reyes",
                "groupOrRoleName": null
              }
            ]
          }
        ]
      }
    ]
  },
  "warnings": [],
  "errors": []
}
```

Three fields carry most of the value:

- `requiresApproval` — `false` when no configured path applies. Use it to skip the approval step entirely rather than submitting and discovering nothing happened.
- `willTrigger` on each path, with `triggerReason` — tells you *why* a path applies, in terms you can show a rep.
- `approvers` on each step — the people who will actually be asked, resolved from users, groups, or roles.

:::hint{type="info"}
**Preview is the cheapest guardrail you can build**

Because it persists nothing, you can call preview on every quote save. Surfacing "this discount needs VP sign-off" while the rep is still editing is far cheaper than discovering it after submission.
:::

## Submit for Approval

Submits a record into its approval process. The record is locked according to the process configuration.

```javascript
POST /cpq/approvals:submit
```

| Field              | Type   | Description                                           |
| ------------------ | ------ | ----------------------------------------------------- |
| `recordId`         | string | **Required.** The record being submitted              |
| `processName`      | string | Omit to let the engine resolve the applicable process |
| `submittedMessage` | string | Comment recorded on the submission                    |
| `source`           | string | `UI`, `Email`, `API`, or `Flow`. Defaults to `API`    |

```bash
curl -X POST 'https://api.nue.io/cpq/approvals:submit' \
  -H 'nue-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "recordId": "0Q0Kb000000XyZaKAK",
    "submittedMessage": "Discount approved by regional director on the call",
    "source": "API"
  }'
```

```json
{
  "status": "SUCCESS",
  "data": {
    "requestId": "a0TKb000000VwCdMAK",
    "recordId": "0Q0Kb000000XyZaKAK",
    "status": "Pending",
    "isLocked": true,
    "approvers": [
      {
        "approvalId": "a0UKb000000WxDeMAK",
        "stepName": "Deal Desk",
        "stepStatus": "Pending",
        "approverUserId": "005Kb000000WxYzIAK",
        "originalApproverUserId": null,
        "reassignedFromApprovalId": null,
        "rejectionMessage": null
      }
    ],
    "approvals": []
  },
  "warnings": [],
  "errors": []
}
```

`isLocked` tells you whether the record is now read-only. Reflect it in your UI so a rep isn't offered an edit that will fail.

## Recall a Submission

Pulls a submitted record back out of its approval process so it can be edited again, unlocking it and revoking the outstanding approvals.

```javascript
POST /cpq/approvals:recall
```

| Field         | Type   | Description                                                 |
| ------------- | ------ | ----------------------------------------------------------- |
| `recordId`    | string | **Required.** The record whose submission is being recalled |
| `processName` | string | Omit to let the engine resolve the applicable process       |
| `actor`       | string | Salesforce User ID to act on behalf of                      |
| `source`      | string | `UI`, `Email`, `API`, or `Flow`. Defaults to `API`          |

```bash
curl -X POST 'https://api.nue.io/cpq/approvals:recall' \
  -H 'nue-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{ "recordId": "0Q0Kb000000XyZaKAK" }'
```

Recall is the supported way to correct a quote mid-approval. Editing around a locked record leaves the approval history inconsistent with what was actually approved.
