message/markAsUnread
Add the UNREAD label to a Gmail message, restoring its unread state programmatically.
When to Use
- Flag for human follow-up: A workflow partially processes an email (e.g. extracts data) but determines human review is required — mark it as unread to signal a team member to take action.
- SLA tracking reset: Restore unread state on an email that was incorrectly marked as read before a response SLA clock should have started.
- Error recovery re-queue: After a downstream processing failure, mark the source email as unread so it is picked up again on the next workflow polling cycle.
- Deferred processing signal: Mark an email as unread to defer it for processing in the next scheduled workflow run without custom state storage.
- Human-requested reopen: A support agent requests that a closed email be re-queued — the workflow marks it as unread to return it to the active inbox.
Configuration
Connection
| Field | Type | Description |
credentialId | Guid required | OAuth2 credential ID from BizFirst Credentials Manager. Requires gmail.modify scope. |
Operation Fields
| Field | Type | Default | Description |
messageId | string required | — | Gmail message ID to mark as unread. Adds the system UNREAD label. |
Sample Configuration
{
"nodeType": "Gmail",
"operation": "message/markAsUnread",
"credentialId": "a3f9d12b-44e1-4c89-b7d2-9f0a1e2b3c4d",
"messageId": "{{needsHumanReview.messageId}}"
}
Validation Errors
| Error | Cause | Resolution |
MISSING_FIELD: messageId | messageId is empty | Ensure upstream node provides a valid message ID |
MESSAGE_NOT_FOUND | Message does not exist in the account | Verify message ID comes from the authenticated account |
INVALID_CREDENTIAL | OAuth token expired or credential not found | Re-authenticate in BizFirst Credentials Manager |
PERMISSION_DENIED | Credential lacks gmail.modify scope | Re-grant OAuth permissions with the correct scope |
Output
Success Port
| Field | Type | Description |
success | bool | true when the UNREAD label was added |
status | string | success |
errorCode | string | Empty on success |
Error Port
On failure, routes to the error port with status: "error", errorCode, and errorMessage.
Sample Output
{
"success": true,
"status": "success",
"errorCode": ""
}
Expression Reference
| Expression | Resolves To | Example Use |
{{needsHumanReview.messageId}} | Message ID routed to human review queue | messageId field |
{{catchBlock.failedMessage.messageId}} | Message ID from a failed downstream node | Re-queue via markAsUnread |
{{slaReset.targetMessageId}} | Message ID for SLA clock reset | SLA re-queue operation |
Node Policies & GuardRails
| Policy | Rule |
| Idempotency | Calling markAsUnread on an already-unread message is safe — it is a no-op with a success response |
| Infinite Loop Risk | Do not use markAsUnread in a polling workflow without a separate re-processing flag — it can cause the same email to be processed infinitely |
| Credential Storage | Store OAuth credentials in BizFirst Credentials Manager — never hardcode tokens in workflow configuration |
| Quota Management | markAsUnread (modify) costs minimal quota units — safe for batch and frequent use |
| State Signaling | Use a dedicated workflow state variable or label in addition to unread status for reliable re-processing logic |
| Test Isolation | Test mark-as-unread workflows against a dedicated Gmail test account before connecting production |
Examples
Example 1: Flag for Human Review
A classification node detects an email requires human intervention — mark it as unread to surface it in the agent's inbox.
{
"nodeType": "Gmail",
"operation": "message/markAsUnread",
"credentialId": "a3f9d12b-44e1-4c89-b7d2-9f0a1e2b3c4d",
"messageId": "{{classifier.escalationMessageId}}"
}
Example 2: Error Recovery Re-Queue
A CatchBlock detects a downstream processing failure and re-queues the source email by marking it unread.
{
"nodeType": "Gmail",
"operation": "message/markAsUnread",
"credentialId": "a3f9d12b-44e1-4c89-b7d2-9f0a1e2b3c4d",
"messageId": "{{catchBlock.sourceMessageId}}"
}
Example 3: Deferred Processing Signal
A rate-limiting check determines the workflow cannot process more messages this cycle — mark remaining as unread for the next run.
{
"nodeType": "Gmail",
"operation": "message/markAsUnread",
"credentialId": "a3f9d12b-44e1-4c89-b7d2-9f0a1e2b3c4d",
"messageId": "{{loop.current.messageId}}"
}