POST /v1/projects/:projectId/ads/:platform/pending/:pendingId/{approve,reject}
Approve or reject a pending optimizer action queued by the gate's `draft` axes.
POST
/v1/projects/:projectId/ads/{platform}/pending/:pendingId/approvePhase 1stable
- Auth
- Bearer
- Scope
- ads:write:pending
POST
/v1/projects/:projectId/ads/{platform}/pending/:pendingId/rejectPhase 1stable
- Auth
- Bearer
- Scope
- ads:write:pending
Approve or reject a pending optimizer action. Approved actions dispatch on the optimizer's next 6h tick (or earlier if you trigger a fresh optimizer run). Rejected actions are flagged and never dispatch.
Approve body
Body (optional)
commentstringoptionalFree-form note attached to the approval audit row.
Reject body
Body
reasonstringrequiredWhy the action was rejected. Surfaces in the audit log + on customer-side optimizer dashboard.
Approve request
curl -X POST https://api.layers.com/v1/projects/$PROJECT_ID/ads/meta/pending/$PENDING_ID/approve \
-H "Authorization: Bearer $LAYERS_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "comment": "Looks good — spend pacing is on target." }'Response
{
"pendingId": "pa_01HZX9...",
"status": "approved",
"dispatched": false,
"dispatchedAt": null,
"verdictId": "ver_01HZX9..."
}dispatched: false is the immediate state — the optimizer's next tick (within 6 hours) executes the approved action. The approval.dispatched webhook fires when the platform-side mutation lands; dispatchedAt populates on the next read.
Errors
| Code | When |
|---|---|
NOT_FOUND | Pending action doesn't exist or is already terminal. |
FORBIDDEN_SCOPE | Key lacks ads:write:pending. |
CONFLICT | Pending action is already approved/rejected/dispatched. |