Approval Queues
Review, approve, reject, edit, and escalate held messages using the override queue API.
When a mailbox is set to autonomy level L1 or L2, outbound sends are held for review before delivery. The approval queue API lets your agents or human operators inspect held messages and take action on each one.
How queues work
After the policy engine approves a send, the mailbox's autonomy level is evaluated:
- L3 - send executes immediately
- L2 - first message to a new contact is held; subsequent messages to known contacts execute immediately
- L1 - every send is held regardless of contact history
Held messages appear in the approval queue. Inbound messages flagged by the safety classifier (phishing, malware, abuse, impersonation) are also routed to the approval queue. Spam-classified messages go to a separate spam queue - see Inbound Email for spam queue documentation.
Queue types
| Queue | Contents |
|---|---|
needs_approval_outbound | Outbound sends held by autonomy level |
needs_approval_inbound | Inbound messages held by safety classifier |
blocked_by_policy | Sends blocked hard by the policy engine |
high_risk | Messages flagged as high-risk |
spam | Inbound messages classified as spam |
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /v1/agent/override/queues/counts | Get counts per queue |
| GET | /v1/agent/override/queues/:queue | List items in a queue |
| GET | /v1/agent/override/held-messages | List held messages |
| POST | /v1/agent/override/held-messages/:messageId/release | Release a held message |
| POST | /v1/agent/override/held-messages/:messageId/reject | Reject a held message |
| POST | /v1/agent/override/:threadId/approve | Approve a thread for sending |
| POST | /v1/agent/override/:threadId/reject | Reject a thread |
| POST | /v1/agent/override/:threadId/edit | Edit a held message before release |
| POST | /v1/agent/override/:threadId/escalate | Escalate to a human reviewer |
All endpoints require Bearer authentication and operator API key scope.
Queue counts
Get the current item count for each queue. Use this as a lightweight check before listing queue contents.
GET https://api.molted.email/v1/agent/override/queues/countscurl "https://api.molted.email/v1/agent/override/queues/counts?tenantId=TENANT_ID" \
-H "Authorization: Bearer YOUR_API_KEY"Query parameters
| Parameter | Type | Description |
|---|---|---|
tenantId | string | Your tenant ID |
mailboxId | string | Scope counts to a specific mailbox |
Response
{
"needs_approval_outbound": 3,
"needs_approval_inbound": 1,
"blocked_by_policy": 0,
"high_risk": 0,
"spam": 5
}CLI
molted overrides countsList queue items
List the items in a specific queue.
GET https://api.molted.email/v1/agent/override/queues/:queuecurl "https://api.molted.email/v1/agent/override/queues/needs_approval_outbound?tenantId=TENANT_ID&limit=25" \
-H "Authorization: Bearer YOUR_API_KEY"Path parameters
| Parameter | Description |
|---|---|
queue | Queue name: needs_approval_outbound, needs_approval_inbound, blocked_by_policy, high_risk, spam |
Query parameters
| Parameter | Type | Description |
|---|---|---|
tenantId | string | Your tenant ID |
mailboxId | string | Filter to a specific mailbox |
direction | string | Filter by direction: inbound, outbound |
limit | integer | Max items (1-50, default 25) |
offset | integer | Pagination offset |
CLI
molted overrides queue needs_approval_outbound --limit 10List held messages
List messages that are held pending approval for a tenant or thread.
GET https://api.molted.email/v1/agent/override/held-messagescurl "https://api.molted.email/v1/agent/override/held-messages?tenantId=TENANT_ID" \
-H "Authorization: Bearer YOUR_API_KEY"Query parameters
| Parameter | Type | Description |
|---|---|---|
tenantId | string | Your tenant ID |
threadId | string | Filter to messages in a specific thread |
CLI
molted overrides held-messages
molted overrides held-messages --thread-id thr_abc123Release a held message
Send the message as originally requested.
POST https://api.molted.email/v1/agent/override/held-messages/:messageId/releasecurl -X POST "https://api.molted.email/v1/agent/override/held-messages/msg_abc123/release?tenantId=TENANT_ID" \
-H "Authorization: Bearer YOUR_API_KEY"CLI
molted overrides release msg_abc123Reject a held message
Discard the message without sending it.
POST https://api.molted.email/v1/agent/override/held-messages/:messageId/rejectcurl -X POST "https://api.molted.email/v1/agent/override/held-messages/msg_abc123/reject?tenantId=TENANT_ID" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "reason": "Content not appropriate for this contact" }'Request body
| Field | Type | Description |
|---|---|---|
reason | string | Optional reason for rejection |
CLI
molted overrides reject msg_abc123 --reason "Content not appropriate"Approve a thread
Approve a held outbound send on a thread. The message is released for delivery.
POST https://api.molted.email/v1/agent/override/:threadId/approvecurl -X POST "https://api.molted.email/v1/agent/override/thr_abc123/approve?tenantId=TENANT_ID" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reason": "Content reviewed - looks good",
"recipientEmail": "alice@example.com",
"templateId": "welcome",
"dedupeKey": "welcome-alice-approved-1",
"payload": { "name": "Alice" }
}'Request body
| Field | Type | Required | Description |
|---|---|---|---|
reason | string | Yes | Why you are approving this send |
templateId | string | No | Override the template for this send |
recipientEmail | string | No | Override the recipient |
dedupeKey | string | No | Override the deduplication key |
payload | object | No | Override the template payload |
CLI
molted overrides approve thr_abc123 --reason "Looks good" \
--template welcome --to alice@example.com \
--dedupe-key "approved-alice-1" --payload '{"name": "Alice"}'Reject a thread
Reject a held send on a thread. The message is discarded.
POST https://api.molted.email/v1/agent/override/:threadId/rejectcurl -X POST "https://api.molted.email/v1/agent/override/thr_abc123/reject?tenantId=TENANT_ID" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "reason": "Wrong template selected" }'Request body
| Field | Type | Required | Description |
|---|---|---|---|
reason | string | Yes | Why you are rejecting this send |
CLI
molted overrides reject-send thr_abc123 --reason "Wrong template"Edit a held message
Modify a held message before releasing it. Use this to adjust routing or metadata without discarding the message entirely.
POST https://api.molted.email/v1/agent/override/:threadId/editcurl -X POST "https://api.molted.email/v1/agent/override/thr_abc123/edit?tenantId=TENANT_ID" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reason": "Adjusted tone before sending",
"metadata": { "reviewed_by": "supervisor-agent" }
}'Request body
| Field | Type | Required | Description |
|---|---|---|---|
reason | string | Yes | Why you are editing the message |
assignedAgentId | string | No | Reassign the thread to a different agent |
metadata | object | No | Update thread metadata |
CLI
molted overrides edit thr_abc123 --reason "Adjusted tone" \
--agent-id agt_abc --metadata '{"reviewed": true}'Escalate a thread
Route a thread to a human reviewer or a named team when the agent cannot decide.
POST https://api.molted.email/v1/agent/override/:threadId/escalatecurl -X POST "https://api.molted.email/v1/agent/override/thr_abc123/escalate?tenantId=TENANT_ID" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reason": "Complex legal question - needs human review",
"assignTo": "legal-team"
}'Request body
| Field | Type | Required | Description |
|---|---|---|---|
reason | string | Yes | Why you are escalating |
assignTo | string | No | Name or identifier of the team or person to escalate to |
CLI
molted overrides escalate thr_abc123 \
--reason "Complex legal question" \
--assign-to "legal-team"Supervisor agent pattern
A common pattern for agents managing L1 or L2 mailboxes is a periodic supervisor loop:
# 1. Check queue depth
molted overrides counts
# 2. Review pending items
molted overrides queue needs_approval_outbound --limit 25
# 3. For each item: approve, reject, edit, or escalate
molted overrides approve thr_abc123 --reason "Reviewed"
molted overrides reject-send thr_def456 --reason "Off-brand"
molted overrides escalate thr_ghi789 --reason "Needs legal sign-off"
# 4. Repeat on intervalTo integrate programmatically, poll the queues/counts endpoint and trigger your review logic when counts exceed a threshold. Use webhooks or events to get notified without polling.