Approvals
BetaManager sign-off above org-configured limits (discount %, credit, PO total, expense amount). A document that needs approval can't be finalised: writes return 409 approval_required with the reasons, or hold it when the body has submitForApproval: true.
/api/v1/approvalsList approval requests
approvals.readParameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
status | query | string | Optional | PENDING, APPROVED, REJECTED or CANCELLED. |
docType | query | string | Optional | QUOTE, SALES_ORDER, INVOICE, PURCHASE_ORDER or EXPENSE. |
page | query | number | Optional | 1-based page number. |
limit | query | number | Optional | Page size, max 200. |
Example request
curl "https://invoice.avscorp.in/api/v1/approvals" \
-H "Authorization: Bearer YOUR_API_KEY"Example response
{
"id": "clx9apr00000000000000001",
"docType": "INVOICE",
"docId": "clx2inv001000000000000001",
"status": "PENDING",
"reasons": [
{
"rule": "DISCOUNT_PERCENT",
"message": "Discount 18% exceeds the 10% limit",
"value": "18",
"limit": "10"
}
],
"snapshot": {
"totalBase": "11800",
"currencyCode": "INR",
"exchangeRate": "1",
"maxDiscountPct": "18",
"customerId": "clx1cus000000000000000001"
},
"requestedBy": "clxusr0000000000000000002",
"decidedBy": null,
"decidedAt": null,
"decisionNote": null,
"cancelReason": null,
"createdAt": "2026-10-26T10:00:00.000Z"
}Possible errors: unauthorized, insufficient_scope, forbidden, validation_error
/api/v1/approvalsSubmit a draft for approval
approvals.readRe-evaluates the saved draft (or held expense). Returns { needed: false } when no rule trips any more. Also needs the document's own update scope (expenses.create for expenses).
Request body
| Field | Type | Required | Constraints |
|---|---|---|---|
docType | string | Required | one of: QUOTE, SALES_ORDER, INVOICE, PURCHASE_ORDER, EXPENSE |
docId | string | Required | min length 1; max length 30 |
Example request
curl -X POST "https://invoice.avscorp.in/api/v1/approvals" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"docType": "INVOICE",
"docId": "clx2inv001000000000000001"
}'Example response
{
"needed": true,
"requestId": "clx9apr00000000000000001",
"reasons": [
{
"rule": "DISCOUNT_PERCENT",
"message": "Discount 18% exceeds the 10% limit",
"value": "18",
"limit": "10"
}
]
}Possible errors: unauthorized, insufficient_scope, forbidden, not_found, conflict, validation_error
/api/v1/approvals/{id}/approveApprove a request
approvals.approveOnly PENDING requests; nobody approves their own. Approving an expense posts it.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Required | Approval request ID. |
Example request
curl -X POST "https://invoice.avscorp.in/api/v1/approvals/clx9apr00000000000000001/approve" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"note": "OK for this customer"
}'Example response
{
"id": "clx9apr00000000000000001",
"docType": "INVOICE",
"docId": "clx2inv001000000000000001",
"status": "APPROVED",
"reasons": [
{
"rule": "DISCOUNT_PERCENT",
"message": "Discount 18% exceeds the 10% limit",
"value": "18",
"limit": "10"
}
],
"snapshot": {
"totalBase": "11800",
"currencyCode": "INR",
"exchangeRate": "1",
"maxDiscountPct": "18",
"customerId": "clx1cus000000000000000001"
},
"requestedBy": "clxusr0000000000000000002",
"decidedBy": "clxusr0000000000000000001",
"decidedAt": "2026-10-26T11:00:00.000Z",
"decisionNote": null,
"cancelReason": null,
"createdAt": "2026-10-26T10:00:00.000Z"
}Possible errors: unauthorized, insufficient_scope, forbidden, not_found, conflict
/api/v1/approvals/{id}/rejectReject a request
approvals.approveA note is required. The document stays a draft (an expense stays held).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Required | Approval request ID. |
Example request
curl -X POST "https://invoice.avscorp.in/api/v1/approvals/clx9apr00000000000000001/reject" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"note": "Discount too high for this account"
}'Example response
{
"id": "clx9apr00000000000000001",
"docType": "INVOICE",
"docId": "clx2inv001000000000000001",
"status": "REJECTED",
"reasons": [
{
"rule": "DISCOUNT_PERCENT",
"message": "Discount 18% exceeds the 10% limit",
"value": "18",
"limit": "10"
}
],
"snapshot": {
"totalBase": "11800",
"currencyCode": "INR",
"exchangeRate": "1",
"maxDiscountPct": "18",
"customerId": "clx1cus000000000000000001"
},
"requestedBy": "clxusr0000000000000000002",
"decidedBy": "clxusr0000000000000000001",
"decidedAt": null,
"decisionNote": "Discount too high for this account",
"cancelReason": null,
"createdAt": "2026-10-26T10:00:00.000Z"
}Possible errors: unauthorized, insufficient_scope, forbidden, not_found, conflict, validation_error