Subscribe to inbox events and receive notifications. Event notifications cover operational events — incoming messages, label changes, cap thresholds — and contact date events such as birthdays and anniversaries, which fire once per year on the matching date. Two delivery types are supported: webhook (HTTP POST to a URL) and task (creates a task in the inbox's Tasks calendar).
GET /v1/events/reference/ List available event types no auth required; admins see admin-only types
"admin": true.GET /v1/events/types/ List event type options no auth required; admins see admin-only types
GET /v1/alerts/?inbox_id= List event notifications for an inbox scope: alerts:read
POST /v1/alerts/ Create an event notification scope: alerts:write
| Field | Type | Required | Description |
|---|---|---|---|
| inbox_id | string | required | — |
| events | array | required | — |
| offset | object | optional | Fire before the event — e.g. {"value": 2, "unit": "days"}. |
| filter | object | optional | — |
| retries | number | optional | Default 3. |
| backoff | string | optional | One of: immediate, fixed, exponential. |
| Field | Type | Required | Description |
|---|---|---|---|
| delivery.type | string | required | Set to task. |
| delivery.target | string | required | Summary template — supports {field} interpolation from the event payload. |
| Field | Type | Required | Description |
|---|---|---|---|
| threshold | number | optional | Percentage of cap for cap.reached events. |
GET /v1/alerts/{id}/ Get an event notification scope: alerts:read
PATCH /v1/alerts/{id}/ Update an event notification scope: alerts:write
| Field | Type | Required | Description |
|---|---|---|---|
| events | array | optional | — |
| delivery | object | optional | — |
| offset | object | optional | — |
| threshold | number | optional | Percentage of cap for threshold-based events. |
| filter | object | optional | — |
| enabled | boolean | optional | — |
| retries | number | optional | — |
| backoff | string | optional | — |
DEL /v1/alerts/{id}/ Delete an event notification scope: alerts:write
webhook — POST a JSON payload to the target URL; supports retries and backoff. When the deployment has GENT_WEBHOOK_SECRET configured, event notification webhooks include X-Gent-Signature: sha256=<hex>. Event notifications do not accept a per-alert secret field. task — create a task in the inbox's Tasks calendar; target is a summary template that supports {field} interpolation from the event payload (e.g. "Alert: {type}"); retries and backoff are ignored.| Event type | Category | Fires when | Config |
|---|---|---|---|
| Messaging | |||
message.received | Messaging | A new inbound message arrives in the inbox | — |
message.sent | Messaging | An outbound message is sent successfully | — |
message.delivered | Messaging | Recipient mail server confirmed delivery. Payload: message_id, thread_id, recipients[] (address, smtp_reply) | — |
message.bounced | Messaging | One or more recipients rejected the message. Payload: message_id, thread_id, recipients[] (address, smtp_reply, bounce_category). Hard bounces auto-suppressed. | — |
message.missed_reply | Messaging | A sent message has received no reply after the inbox's missed_reply_threshold_days. Payload: message_id, to_address, days_since_sent. Auto-subscribed when threshold is set. | — |
message.spam_complaint | Messaging | A recipient marked a sent message as spam. Payload: recipient, feedback_type. Recipient is auto-suppressed. Requires spam feedback registration with each ISP. | — |
| Labels | |||
label.applied | Labels | A label is applied to a message or contact | — |
label.suggested | Labels | Label inference pipeline finds suggestions for a new message. Payload: message_id, suggestions[] (label_id, label_name, confidence). Requires label_suggest feature. | — |
| Calendar | |||
event.created | Calendar | Time-based reminder scanned hourly — fires at scheduled start minus offset. Fires for all upcoming non-cancelled events. Units: minutes · hours · days. | offset |
event.updated | Calendar | Same as event.created but distinct stream for modified events. | offset |
event.cancelled | Calendar | Fires immediately when an event is deleted or patched to status: "cancelled". offset shifts relative to original start. | offset |
event.suggested | Calendar | Meeting/call detected in inbound message. Payload: message_id, title, start. Requires calendar_suggest feature. | — |
| Contacts & relationships | |||
contact.{type} | Anniversary | Scanned daily. Fires when a contact's anniversary month/day matches today (or today − offset days). E.g. contact.birthday, contact.work_anniversary. Use contact.any to match all types. offset only supports unit: "days". Deduped once per calendar year per contact. Optional filter: {"contact_id": "..."}. | offset (days only) |
contact.share_received | Contacts | A contact share offer or request arrives. Fires on the recipient inbox (offer) or contact-holder inbox (request). | — |
contact.handoff_received | Contacts | A contact has been handed off to this inbox by a team member. | — |
| Thresholds & account | |||
cap.reached | Threshold | Send or spend cap crosses the configured level | threshold (% of cap) |
storage.threshold | Threshold | Message and attachment storage crosses the configured level | threshold (% of limit) |
auth.failed | Threshold | Consecutive API auth failures reach the count | threshold (count) |
billing.cost_threshold | Billing | Monthly spend crosses a USD amount. Edge-triggered — fires once per calendar month. | threshold (USD) |
billing.projected_overage | Billing | Projected month-end spend (linear extrapolation) crosses a USD amount. | threshold (USD) |
domain.expiring | Account | A registered domain is nearing its expiry date | — |
| Security & intelligence | |||
phishing.detected | Security | Inbound message classified as phishing (confidence ≥ 0.8). Payload: message_id, score. | — |
email.high_priority | Intelligence | Inbound message classified as high priority by the AI layer. Payload: message_id. Requires next_step feature. | — |
| Workflow | |||
workflow_rule_matched | Workflow | A workflow's notify action fired. Payload: inbox_id, message_id, trigger, context. | — |
approval.* | Approvals | approval.queued — action held for review. approval.approved — approved and executed. approval.rejected — rejected. Payload: approval_id, action_type, summary. | — |
| Files | |||
file.created | Files | A file was created. Payload: file_id, name, file_type, folder_id, source_message_id, collaborators. | — |
file.updated | Files | File metadata was updated. Payload: file_id, name, file_type, collaborators. | — |
file.version_added | Files | New content version saved. Payload: file_id, name, version_number, source_message_id, collaborators. Fires on update_document workflow write and direct uploads. | — |
file.rows_appended | Files | Rows appended to a spreadsheet. Payload: file_id, name, rows_added, source_message_id, collaborators. Fires on append_rows workflow write and direct API writes. | — |
file.deleted | Files | A file was permanently deleted. Payload: file_id, name, file_type. | — |
Event-driven rules that perform writes when inbox or tenant events occur. Each rule has a trigger, optional conditions to filter the event context, and one or more source-to-target writes. Rules are owned by the creating actor — only the creator can read or modify them. Endpoints in this section accept session auth or an agent token with the required workflow scope.
GET /v1/workflows/reference/ List workflow builder options scope: workflows:read
"available": false and "unavailable_reason": "requires_higher_workflow_tier". Write target fields define payload fields, widgets, defaults, required validation, fixed options, and picker source endpoints that builders should render.writes. Gent derives the target fields, extracts values from the source, validates required fields, and either writes the result or holds it for review. Advanced reference output can include lower-level preparation phases for clients that need explicit chains.GET /v1/workflows/write-templates/ List reusable workflow writes scope: workflows:read
POST /v1/workflows/write-templates/ Create a reusable write → template_id scope: workflows:write
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | required | Human-readable template name. |
| tenant_id | string | optional | Use for tenant-scoped reusable writes. |
| inbox_id | string | optional | Use when the write is tied to an inbox-scoped resource. |
| source | object | required | Same source object used in rule writes[]. |
| target | object | required | Same target object used in rule writes[]. |
| contract, policy, review_policy | object | optional | Default contract and review behavior to reuse when a rule references this template. |
GET /v1/workflows/write-templates/{template_id}/ Get a reusable write scope: workflows:read
PATCH /v1/workflows/write-templates/{template_id}/ Update a reusable write scope: workflows:write
DEL /v1/workflows/write-templates/{template_id}/ Delete a reusable write scope: workflows:write
writes.POST /v1/workflows/recipes/validate/ Validate TOML recipe scope: workflows:read
| Field | Type | Required | Description |
|---|---|---|---|
| toml | string | required | Workflow recipe TOML. Must use kind = "gent.workflow_recipe". |
| inputs | object | optional | Setup values used to resolve {{ inputs.name }} placeholders for preview. |
GET /v1/workflows/ List your rules
POST /v1/workflows/ Create a rule → rule_id
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | required | Unique per creator, used as URL key. |
| trigger | string | required | See Triggers table below. |
| inbox_id | string | required | Required for inbox-scoped triggers. |
| tenant_id | string | optional | Defaults to the authenticated user's tenant for tenant-scoped triggers. |
| conditions | array | optional | All conditions must match. |
| writes | array | required | One or more source-to-target writes. Raw actions are not accepted. |
GET /v1/workflows/{rule_id}/ Get a rule by name
PATCH /v1/workflows/{rule_id}/ Update a rule
| Field | Type | Required | Description |
|---|---|---|---|
| conditions | array | optional | Replaces existing. |
| writes | array | optional | Replaces existing writes. Raw actions are not accepted. |
| priority | number | optional | — |
DEL /v1/workflows/{rule_id}/ Delete a rule
GET /v1/workflows/triggers/ List usable triggers scope: workflows:read
GET /v1/workflows/conditions/ List condition operators scope: workflows:read
GET /v1/workflows/write-targets/ List write target contracts scope: workflows:read
POST /v1/workflows/{rule_id}/test/ Dry-run a rule scope: workflows:read
| Field | Type | Required | Description |
|---|---|---|---|
| message_id | string | optional | Test against a specific message; omit to use the most recent. |
| trigger | Scope | Permission | Context fields available in conditions & action templates |
|---|---|---|---|
| Inbox — email | |||
email_received | inbox | user | from_address, from_name, from_domain, to_address, subject, has_attachments, body_preview, thread_id, sender_label_ids |
email_sent | inbox | user | from_address, from_name, from_domain, to_address, subject, has_attachments, body_preview, thread_id |
missed_reply | inbox | user | message_id, to_address, days_since_sent, subject. Fires when a sent message has no reply after missed_reply_threshold_days. |
message_bounced | inbox | user | recipient, bounce_category (hard·soft·spam_policy·unknown), smtp_reply |
spam_complaint_received | inbox | user | recipient. Fires when a recipient marks a sent message as spam. |
label_applied | inbox | user | label_id, label_name, message_id, thread_id, from_address, subject, body_preview. Fires when any label is applied to a message — use a condition to match a specific label. Can start sequences or work routes when the labeled email has sender context. |
| Inbox — contacts & threads | |||
contact_created | inbox | user | email, email_domain |
thread_assigned | inbox | user | thread_id, assigned_from, subject. Fires on the assignee inbox. |
contact_unsubscribed | inbox | user | email, label_id (broadcast label the contact opted out of) |
calendar_event_created | inbox | user | organizer, organizer_domain, title |
| Inbox — files | |||
file_created | inbox | user | file_id, name, file_type, folder_id, source_message_id. Fires when any file is created — use a condition to match by file_type or folder_id. |
file_updated | inbox | user | file_id, name, file_type, folder_id. Fires on metadata changes. |
file_version_added | inbox | user | file_id, name, file_type, version_number, source_message_id. Fires when a new content version is saved. |
file_rows_appended | inbox | user | file_id, name, rows_added, source_message_id. Fires when rows are appended to a spreadsheet. |
| Tenant — admin only | |||
invite_redeemed | tenant | admin | invite_batch_label, role, email, email_domain |
quota_threshold_hit | tenant | admin | inbox_id, metric, value, limit |
cap_released | tenant | admin | inbox_id, cap_type |
billing_event | tenant | admin | event_type, amount |
| op | Behaviour | value |
|---|---|---|
eq | Exact match (string, bool, or number) | String / bool / number |
contains | Substring match | String |
in | Field value is one of a list | Array of strings |
includes | Field is a list and value is present in it — used with sender_label_ids | String (single item to check) |
any | Always true — match every event regardless of field value | Omit |
ai | LLM evaluates whether the natural-language description is true for the trigger context. Fails closed — returns false on LLM errors or missing config. Counts toward LLM usage. | Natural language description, e.g. "The email sounds urgent" |
| target | Additional fields | Notes |
|---|---|---|
writes[] | "source": {"from": "trigger.file|trigger.email|trigger.attachment|trigger.embedded_image|event.payload"}, "target": {"type": "file.spreadsheet.rows", "file_id": "<spreadsheet-id>"} or any target from /v1/workflows/reference/; "policy" is optional | The public write surface. Gent derives target fields, extracts values from the source, validates required fields, and either commits the result or holds it for review. |
source.extract | "task": "extract_invoice", optional "engine", "ocr_engine", and "config" | Intermediary extraction inside a write. Use it when the source needs OCR or structured understanding before the target can be committed. |
source.map | Optional explicit field overrides such as {"Amount": "total_amount"} | Spreadsheet row workflows normally infer target fields from spreadsheet headers. Use map overrides only when inference needs help. |
| Contract targets | ||
email.* | email.add_label, email.move_to_folder, email.reply, email.draft, email.attach_file, and related email mutation targets | Email side effects are selected through target.type, not separate action names. |
file.* | file.spreadsheet.rows, file.create, file.update | Files targets validate access and target schema before committing writes. |
contact.* | contact.ensure, contact.label, contact.note | Contact side effects use the triggering sender or reviewed contract values. |
sequence.enroll, work_route, thread.assign, webhook, alert.notify, task | Target-specific ref fields are listed in /v1/workflows/reference/. | Clients should build UI from the reference endpoint instead of hard-coding old direct write names. |
rule_id. GET /v1/workflows/reference/ is the source for workflow builders. The trigger, condition, and write-target helper lists expose smaller slices of the same contract. Each write target includes compatibility metadata, and the API rejects incompatible trigger/write combinations and invalid extracted-field chains before activation.- Agent token —
workflows:readfor GET,workflows:writefor POST/PATCH/DELETE. Inbox-scoped: only inbox-level triggers available (email_received,email_sent, etc.). - Session token — access via inbox ownership. Tenant-scoped and system triggers require session auth.
- Rules created by a token are owned by the inbox and visible to session auth on the same inbox.
workflow feature tier to be lite or higher. POST and PATCH return 403 Forbidden on plans without workflow access. Workflow count, allowed trigger scopes, and available write targets are also gated by tier — the list endpoint always returns 200 regardless of plan.Workflows can incorporate LLM calls through AI conditions that decide whether a rule should fire and through contract-backed extraction that prepares reviewed values for deterministic targets. These features require an active LLM config on the inbox — see Enrichment for setup.
op: "ai") require workflows:lite or higher. Contract extraction with LLMs requires workflows:full. LLM consent must be enabled on the tenant.Use "op": "ai" as a condition to evaluate the trigger context against a natural-language description. The LLM sees all available context fields for the trigger and returns a boolean. Use this for matching on tone, intent, or content that can't be expressed as a field comparison.
| Behaviour | Detail |
|---|---|
| Fails closed | If the LLM is unavailable, misconfigured, or returns an error, the condition evaluates to false and the rule does not fire. This prevents mis-triggers from propagating when AI is degraded. |
No field key | AI conditions don't filter on a single field — they receive the whole context. Omit "field" entirely. |
| Length | value must be 10–1000 characters. Keep descriptions specific — vague descriptions produce inconsistent results. |
| Test endpoint | POST /v1/workflows/{rule_id}/test/ evaluates AI conditions against a real message and returns each result with a "reasoning" field. AI calls made during testing count toward usage. |
Use writes when a workflow should prepare values from an email, attachment, file, or event payload and then write to a deterministic target. Gent describes the target contract, extracts values, validates required fields, and either commits the result or holds it for review based on the workflow policy.
| Target | What happens |
|---|---|
email.reply / email.draft | Uses reviewed contract values to send a reply or save a draft. Use review policies for uncertain generated text. |
task | Extracts task fields such as summary, description, and due date, then creates a task. |
contact.note | Appends reviewed notes to the sender's contact record. |
file.spreadsheet.rows | Reads the spreadsheet headers, extracts matching values from the source, and appends a row when the contract is ready. |
webhook | Dispatches a validated event payload through the inbox webhook path. |
If extracted values are missing, invalid, or below confidence thresholds, the workflow policy decides whether to hold, skip, fail, or auto-approve. Held workflow writes appear in Approvals with action_type: "workflow:write". Approving commits the reviewed contract result without re-running extraction.
- AI condition descriptions should describe a specific pattern, not a general topic. "Email about billing" is vague; "The sender is questioning a charge or requesting a refund" is precise.
- Combine AI conditions with deterministic conditions to reduce LLM calls — e.g. check
from_domain eq "example.com"first so the AI condition only runs on the relevant subset. - Use target contracts to describe the exact fields required before a side effect commits. Missing or invalid fields should normally hold for review.
- For spreadsheet workflows, keep column headers clear and stable so Gent can map extracted values to the right row fields.
Multi-email follow-up sequences that execute over time. Two modes: template sequences (reusable definitions started via workflow rules) and ad-hoc enrollments (custom per-recipient emails defined inline at enrollment time). Emails use either a static body or a prompt evaluated by the LLM at send time using the enrollment source context.
label_applied and action start_sequence can start a follow-up when a label is applied to an email. For custom per-conversation sequences, clients can call POST /v1/sequences/enrollments/ directly with inline emails and a shared source object. A reply from the contact automatically exits any active exit_on_reply enrollments.workflows:full. Direct API enrollment requires sequences:write scope.GET /v1/sequences/reference/ Sequence builder contract scope: sequences:read
POST /v1/sequences/ Create a reusable sequence template scope: sequences:write
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | required | Human-readable name. |
| emails | array | required | Ordered emails. Each email has delay_days (int), prompt (LLM instruction, evaluated at send time) or body (static text), and optional subject. |
| exit_on_reply | bool | optional | Exit all active enrollments when the contact replies. Default true. |
| exit_condition_prompt | string | optional | LLM instruction for evaluating whether a reply warrants exit (e.g. "exit if the reply indicates the request was fulfilled"). |
| sender_inbox_id | string | optional | Default sending inbox. Overridden at enrollment. |
GET /v1/sequences/ List sequences for the tenant scope: sequences:read
GET /v1/sequences/{sequence_id}/ Get a sequence scope: sequences:read
PATCH /v1/sequences/{sequence_id}/ Update a sequence scope: sequences:write
name, emails, exit_on_reply, exit_condition_prompt, sender_inbox_id. Active enrollments are unaffected — they copied emails at enrollment time.DELETE /v1/sequences/{sequence_id}/ Delete a sequence scope: sequences:write
POST /v1/sequences/enrollments/ Start a sequence enrollment scope: sequences:write
| Field | Type | Required | Description |
|---|---|---|---|
| recipient | object | required | Recipient to enroll: {"contact_id": "..."} or {"email": "..."}. Email recipients create or reuse a contact. |
| inbox_id | string | required | Inbox to send from. |
| sequence_id | string | conditional | Reference a saved sequence. Either this or emails is required. |
| emails | array | conditional | Inline emails for ad-hoc enrollment. Either this or sequence_id is required. |
| source | object | optional | Source captured at enrollment time — injected into each email prompt at send time. |
| exit_on_reply | bool | optional | Exit when the contact replies. Default true. |
GET /v1/sequences/enrollments/ List enrollments scope: sequences:read
| Param | Type | Description |
|---|---|---|
| contact_id | string | Filter to a specific contact. |
| status | string | Filter by status: active, completed, exited, cancelled. |
GET /v1/sequences/enrollments/{enrollment_id}/ Get an enrollment scope: sequences:read
PATCH /v1/sequences/enrollments/{enrollment_id}/ Cancel an enrollment scope: sequences:write
status: "cancelled".Multi-recipient email requests for approvals, acknowledgements, and stakeholder input. A route is owned by a creator inbox, can run recipients in parallel or ordered sequence, stays visible in agenda while active, and records recipient responses as route events.
POST /v1/work-routes/{route_id}/responses/ or the equivalent service method. Use email replies for approval, acknowledgement, and text-response routes.workflows:full. Agent tokens need work_routes:read for reads and work_routes:write for writes.GET /v1/work-routes/reference/ Work route builder contract scope: work_routes:read
completion: "required". Parallel routes allow required, any, and optional.POST /v1/work-routes/ Create a work route scope: work_routes:write
| Field | Type | Required | Description |
|---|---|---|---|
| request_type | string | required | approval, text, or acknowledgement. |
| routing_mode | string | required | parallel activates all recipients at start. ordered activates one recipient at a time. |
| completion | string | required | required, any, or optional. Ordered routes only support required. |
| response_detection | object | optional | Action-keyed reply phrases, such as phrases.approve and phrases.reject. Phrases are shown in the routing email and used before learned/global detection. |
| recipients | array | required | Each recipient is a contact, email, or inbox. Ordered routes may include positive unique order values. |
| reminder_sequence_id | string | optional | Auto-enrolled when the recipient becomes active and has a contact_id. Email-only recipients are routed but reminder enrollment is skipped. |
POST /v1/work-routes/{route_id}/responses/ Record a recipient response scope: work_routes:write
GET /v1/work-routes/reference/. Approval routes support approve, reject, and request_changes. Text routes use submitted; acknowledgement routes use acknowledged. Accepted responses are visible in route status and agenda; no recipient confirmation email is sent.POST /v1/work-routes/response-phrases/ Confirm a learned reply phrase tenant admin
| Field | Type | Required | Description |
|---|---|---|---|
| request_type | string | required | approval, text, or acknowledgement. |
| action | string | required | Must be valid for the request type. |
| phrase | string | required | The short reply text to match deterministically in future email replies. |
| tenant_id | string | optional | System admins only. Tenant admins record phrases for their own tenant. |
| locale | string | optional | Locale hint. Defaults to *. |
| confidence | number | optional | 0 to 1 confidence score for the reviewed classification. |
GET /v1/work-routes/ List routes for an inbox scope: work_routes:read
| Param | Type | Description |
|---|---|---|
| inbox_id | string | Creator inbox. Agent tokens derive this from the token inbox. |
| status | string | Optional route status filter. |