Endpoints for account creation, session management, MFA, and token refresh. All /auth/ endpoints are unauthenticated unless noted — they do not require a Bearer token.
POST /auth/signup/ Create a new account
POST /auth/signup/confirm/ Confirm email address
POST /auth/login/ Sign in — returns access + refresh tokens
| Field | Type | Required | Description |
|---|---|---|---|
| access_token | string | optional | Short-lived. |
| refresh_token | string | optional | Long-lived. |
{"challenge": "mfa", "session": "..."} instead. Pass session and your TOTP code to POST /auth/mfa/ to complete sign-in.POST /auth/mfa/ Complete MFA challenge — optional, only if MFA is enabled
| Field | Type | Required | Description |
|---|---|---|---|
| session | string | required | From login challenge response. |
| string | required | Email address for the challenged account. | |
| code | string | required | TOTP code. |
POST /auth/refresh/ Renew an expired access token
POST /auth/logout/ Revoke session — requires session token
POST /auth/signup/resend/ Re-send confirmation code
POST /auth/forgot-password/ Request a password reset code
POST /auth/forgot-password/confirm/ Confirm password reset
| Field | Type | Required | Description |
|---|---|---|---|
| code | string | required | 6 digits sent to email. |
| new_password | string | required | Min 8 characters. |
POST /auth/change-password/ Change password session auth
| Field | Type | Required | Description |
|---|---|---|---|
| new_password | string | required | Min 8 characters. |
GET /auth/mfa/status/ Get MFA status for the current user session auth
| Field | Type | Required | Description |
|---|---|---|---|
| enabled | boolean | optional | Whether MFA is active. |
| preferred | string | optional | The configured MFA type, or null. |
POST /auth/mfa/setup/ Begin TOTP enrollment session auth
| Field | Type | Required | Description |
|---|---|---|---|
| secret | string | optional | Raw TOTP secret — show to user or encode as QR. |
| otpauth_uri | string | optional | Standard otpauth URI for QR code generation. |
POST /auth/mfa/setup/confirm/ Confirm TOTP enrollment session auth
| Field | Type | Required | Description |
|---|---|---|---|
| code | string | required | 6-digit TOTP code from the authenticator app. |
DEL /auth/mfa/disable/ Disable MFA for the current user session auth
GET /v1/users/me/ Current user + onboarding status user auth
| next_step value | What to do |
|---|---|
| provisioning | Tenant is still being created — retry in a moment. |
| add_domain | POST /v1/domains/ to register your first domain. |
| verify_domain | Set DNS records, then POST /v1/domains/{name}/verify/. |
| create_inbox | POST /v1/inboxes/ to create your first inbox. |
| null | Onboarding complete. |
Three utility endpoints for time and duration handling. parse converts any datetime string (natural language, relative, ISO 8601) to UTC — useful for constructing calendar event start values from user input. convert takes a UTC datetime and returns its local equivalent in a given timezone — useful for displaying stored values. duration parse converts any duration string (natural language or ISO 8601) to a normalised ISO 8601 duration with total seconds and a human-readable label — useful for display or validation. Note: the calendar duration field already accepts natural language directly.
POST /v1/utils/time/parse/ Parse datetime string → UTC
| Field | Type | Required | Description |
|---|---|---|---|
| input | string | optional | Any supported format. |
| timezone | string | optional | IANA timezone; defaults to inbox default_timezone, then UTC. |
| inbox_id | string | session auth | Session auth only; used to look up default_timezone when timezone is omitted. |
| Category | Examples |
|---|---|
| ISO 8601 | "2024-06-01T10:00:00" · "2024-06-01T10:00:00-05:00" · "2024-06-01T15:00:00Z" |
| Natural date | "June 1, 2024 10am" · "01/06/2024 10:00" · "2024/06/01" |
| Named day | "today" · "tomorrow" · "yesterday" |
| Relative offset | "in 2 hours" · "in 3 days" · "in 1 week" |
| Relative past | "2 hours ago" · "3 days ago" |
| Weekday relative | "next Monday" · "last Friday" |
"June 1 10am"), it is interpreted in timezone (which defaults to the inbox's default_timezone). Inputs with an explicit offset (e.g. -05:00 or Z) use that offset directly and the timezone param only affects the local output.
| Field | Type | Required | Description |
|---|---|---|---|
| utc | string | optional | ISO 8601 UTC — use this as the event start value. |
| local | string | optional | LocalDateTime in the requested timezone. |
| timezone | string | optional | Timezone used for interpretation and local output. |
POST /v1/utils/time/convert/ Convert UTC → local time
| Field | Type | Required | Description |
|---|---|---|---|
| utc | string | optional | ISO 8601 UTC datetime. |
| timezone | string | optional | IANA timezone; defaults to inbox default_timezone, then UTC. |
| inbox_id | string | session auth | Session auth only; used to look up default_timezone when timezone is omitted. |
| Field | Type | Required | Description |
|---|---|---|---|
| utc | string | optional | Echoed back. |
| local | string | optional | LocalDateTime in the requested timezone. |
| timezone | string | optional | Timezone used for local output. |
POST /v1/utils/duration/parse/ Parse duration string → ISO 8601
| Field | Type | Required | Description |
|---|---|---|---|
| input | string | optional | Natural language or ISO 8601 duration. |
| Input | ISO 8601 | Seconds |
|---|---|---|
"30 minutes" | PT30M | 1800 |
"1 hour 30 minutes" | PT1H30M | 5400 |
"2h 15m" | PT2H15M | 8100 |
"2 days" | P2D | 172800 |
"1 week" | P1W | 604800 |
"PT1H30M" (ISO input) | PT1H30M | 5400 |
h / hr / hours, m / min / minutes, d / days, w / weeks, s / sec / seconds. ISO 8601 input is normalised and echoed back unchanged.
| Field | Type | Required | Description |
|---|---|---|---|
| iso | string | optional | ISO 8601 duration — use this as the event duration value. |
| seconds | number | optional | Total seconds. |
| natural | string | optional | Human-readable description. |
Machine-readable reference endpoints and builder contracts generated from the live API.
GET /v1/reference/ List available reference endpoints no auth required
GET /v1/reference/api/ List endpoint, method, auth, scope, and schema metadata no auth required
GET /v1/reference/api/ and show conditional rules that plain OpenAPI schemas cannot express cleanly.| Path | Method | Query contract | Body contract | Response contract | Notes |
|---|---|---|---|---|---|
/v1/activity/ | GET | one of: contact_id, address; inbox_id or token-bound inbox; prefer: contact_id | — | — | Provide contact_id or address. Use contact_id for stable contact identity across email aliases and future channel identities. Session requests must include inbox_id; token requests may use the token-bound inbox. |
/v1/agenda/ | GET | inbox_id or token-bound inbox | — | nested: items[] | Thread items include a source object with normalized email channel metadata when available. |
/v1/billing/caps/files/ | PUT | — | required: limit_gb; rules: limit_gb, mode, alert_thresholds | — | Tenant-level cap. Tenant admins only may mutate it. |
/v1/billing/caps/files/ | DELETE | — | — | — | Tenant-level cap. Tenant admins only may delete it. |
/v1/billing/caps/mailbox/ | GET | inbox_id or token-bound inbox | — | — | — |
/v1/billing/caps/mailbox/ | PUT | inbox_id or token-bound inbox | required: limit_gb; rules: limit_gb, mode, alert_thresholds | — | — |
/v1/billing/caps/mailbox/ | DELETE | inbox_id or token-bound inbox | — | — | — |
/v1/billing/caps/send/ | GET | inbox_id or token-bound inbox | — | — | — |
/v1/billing/caps/send/ | PUT | inbox_id or token-bound inbox | rules: limit, mode | — | — |
/v1/billing/caps/send/ | DELETE | inbox_id or token-bound inbox | — | — | — |
/v1/files/folders/{folder_id}/ | DELETE | — | 1 conditional required rule; rules: contents | — | contents defaults to unparent. Use contents=delete to delete files in the folder. Use contents=move with target_folder_id to move files before deleting the folder. |
/v1/files/{file_id}/ | PATCH | — | optional: name, folder_id, instructions, viewers, collaborators, auto_share_from_thread | — | Move a file by setting folder_id. Set folder_id to null to unparent the file. Changing folder_id, viewers, or collaborators requires manage access. |
/v1/files/{file_id}/versions/ | POST | — | one of: file, content | — | Upload multipart file or JSON content to create a new current version. Previous versions remain available from GET /v1/files/{file_id}/versions/. |
/v1/inboxes/{inbox_id}/imports/ | POST | — | required: source; nested: source, source.auth; rules: source.auth.mode, source.auth.password, options.folders | — | Tenant-admin only. Mail-only import. Contacts, calendars, rules, and continuous sync are not imported. Secrets are write-only and are not returned by the API. |
/v1/messages/ | POST | — | one of: text_body, html_body; 1 conditional required rule | — | Provide text_body or html_body. Provide to when reply_to_message_id is not set. |
/v1/messages/threads/{thread_id}/fork/ | POST | — | required: to; one of: text_body, html_body; nested: ticket | — | Provide text_body or html_body. Optional ticket.class_label_key must use ticket/class/<slug>. |
/v1/messages/threads/{thread_id}/labels/ | POST | — | one of: label_id, label_key | — | Provide label_id or label_key. |
/v1/messages/threads/{thread_id}/ticket/ | POST | — | rules: class_label_key, priority | — | class_label_key must use ticket/class/<slug>. class_label_id must reference a thread-capable ticket class label. |
/v1/messages/threads/{thread_id}/ticket/ | PATCH | — | rules: class_label_key, status, priority | — | class_label_key must use ticket/class/<slug> when present. Use workflow endpoints for resolve, close, and reopen transitions when a note is required. |
/v1/messages/threads/{thread_id}/ticket/close/ | POST | — | required: resolution_note | — | — |
/v1/messages/threads/{thread_id}/ticket/resolve/ | POST | — | required: resolution_note | — | — |
/v1/messages/{message_id}/ | PATCH | — | one of: mark_read, mark_starred, mailbox_id | — | Provide at least one mutable message field. |
/v1/retrieval/config/ | GET | — | — | — | Tenant-admin only. Returns tenant retrieval configuration, model options, source options, and pricing policy. |
/v1/retrieval/config/ | PATCH | — | nested: embedding, chunking, extraction; rules: embedding.model_id, chunking.overlap_chars | — | Tenant-admin only. Refresh, public crawls, and retention default to manual/conservative behavior. OCR can be disabled, local via tesseract, or managed via textract. Runtime packaging/IAM determines whether a provider can execute. |
/v1/retrieval/extraction-tests/ | POST | — | required: file_id; nested: chunking, extraction | — | Tests one readable Files API document with the tenant retrieval config plus optional temporary overrides. Does not index, embed, or persist chunks. Returns status=ocr_required for scanned/image-only documents when OCR is needed but disabled for the request or tenant config. Returns status=ocr_failed when OCR is selected but the provider cannot extract text. |
/v1/retrieval/models/ | GET | — | — | — | Returns the platform allowlisted embedding models visible to this tenant. Vector embedding usage follows provider cost plus 5%. |
/v1/retrieval/runs/ | GET | optional: inbox_id | — | — | — |
/v1/retrieval/runs/ | POST | — | required: bucket_id, task, query; rules: output_type | — | output_type must be allowed by the selected task. |
/v1/retrieval/source-buckets/ | GET | optional: owner_type, owner_id | — | — | — |
/v1/retrieval/source-buckets/ | POST | — | required: name, bucket_type, owner_type, owner_id, sources; nested: sources[] | — | Email sources require scope, then the identifier for that scope. Files sources require folder_id. Contacts, calendar, and intelligence sources require scope and the matching identifier for that scope. Public website sources require allowed_domains; seed_urls must stay inside allowed_domains. |
/v1/retrieval/source-buckets/{bucket_id}/ | PATCH | — | optional: name, bucket_type, sources, policy, index_status | — | When sources are provided, the same source type rules as create apply. |
/v1/retrieval/source-buckets/{bucket_id}/estimate/ | POST | — | forbidden: trigger; nested: chunks[] | — | Use before indexing to show likely chunk and embedding volume. Estimate uses extraction previews for safe local sources and conservative limits for sources that should not be crawled during preflight. |
/v1/retrieval/source-buckets/{bucket_id}/index/ | POST | — | forbidden: trigger; nested: chunks[] | — | trigger is server-managed and must not be supplied. sensitive_source_approved is required when tenant policy requires approval for sensitive source buckets. |
/v1/sequences/ | POST | — | required: name, emails; nested: emails[] | — | Each email step needs body or prompt. |
/v1/sequences/enrollments/ | GET | optional: contact_id, status | — | — | — |
/v1/sequences/enrollments/ | POST | — | required: inbox_id, recipient; one of: sequence_id, emails; nested: recipient, emails[] | — | Provide sequence_id or inline emails. Recipient must identify exactly one contact_id or email. |
/v1/sequences/{sequence_id}/ | PATCH | — | nested: emails[] | — | When emails are provided, each email step needs body or prompt. |
/v1/work-routes/ | POST | — | required: creator_inbox_id, title, request_type, routing_mode, completion, recipients, due_at; 2 conditional rules; nested: recipients[], response_detection.phrases | — | Ordered routes only support completion=required. completion=any and completion=optional require routing_mode=parallel. Each recipient must provide exactly one identifier matching kind. Custom response phrases must include at least one successful action phrase. |
| Path | Resource | Auth | Builder contract |
|---|---|---|---|
/v1/reference/api/ | api | optional | yes |
/v1/tokens/reference/ | tokens | optional | yes |
/v1/events/reference/ | events | optional | yes |
/v1/events/types/ | event_types | optional | no |
/v1/workflows/reference/ | workflows | required | yes |
/v1/workflows/triggers/ | workflow_triggers | required | no |
/v1/workflows/conditions/ | workflow_conditions | required | no |
/v1/workflows/write-targets/ | workflow_write_targets | required | no |
/v1/workflows/write-templates/ | workflow_write_templates | required | yes |
/v1/sequences/reference/ | sequences | required | yes |
/v1/work-routes/reference/ | work_routes | required | yes |
/v1/alerts/reference/ | alerts | none | yes |
/v1/files/reference/ | files | none | yes |
/v1/labels/reference/ | labels | none | yes |
/v1/messages/ticketing/reference/ | message_ticketing | none | yes |
/v1/enrichment/reference/ | enrichment | none | yes |
/v1/enrichment/models/ | enrichment_models | none | no |
/v1/enrichment/features/ | enrichment_features | none | no |
/v1/retrieval/reference/ | retrieval | none | yes |
/v1/domains/reference/ | domains | required | yes |
/v1/domains/dns-record-types/ | domain_dns_record_types | required | no |
/v1/sender-rules/reference/ | sender_rules | required | yes |
/v1/sender-rules/modes/ | sender_rule_modes | required | no |
/v1/forwarding/reference/ | forwarding | required | yes |
/v1/forwarding/condition-types/ | forwarding_condition_types | required | no |
All errors return a consistent JSON body with a machine-readable code and human-readable message.
Validation errors include errors with field-level details. Other errors may omit it and use detail plus message.
| Status | Code | Description |
|---|---|---|
| 400 | validation_error | Missing or invalid parameters |
| 401 | authentication_error | Invalid or missing credentials |
| 403 | permission_denied | Caller lacks permission for this action |
| 404 | not_found | Resource does not exist |
| 409 | conflict | Request conflicts with existing state |
| 429 | rate_limited | Too many requests |
| 502/503 | service_unavailable | A required upstream service is temporarily unavailable |
| 500 | server_error | Unexpected server error |
Gent uses adaptive request throttles to protect delivery quality and prevent abuse. Limits are applied by route category and caller identity, such as IP address, session, token, inbox, tenant, demo session, or webhook target. Exact thresholds may change as traffic patterns change.
| Category | How to handle it |
|---|---|
| Authentication | Use backoff after failed login, signup, password, or MFA attempts. |
| Message reads | Use pagination, cursors, and conditional refresh instead of polling aggressively. |
| Message sends | Request throttles are separate from tenant and inbox send caps. |
| Uploads and downloads | Retry with backoff and avoid parallel retries for the same object. |
| Tracking and public links | High-volume public routes are isolated from authenticated API limits. |
| Webhooks and demo | Demo and webhook test delivery limits are intentionally stricter than production tenant traffic. |
When a request is throttled, the API returns 429 rate_limited. If the reset time is known, the response includes Retry-After. Clients should use exponential backoff with jitter and should not retry unsafe write requests without an Idempotency-Key.
Any POST request can be made idempotent by supplying an
Idempotency-Key header. When the same key is sent again within
24 hours the original response is returned immediately — no action is
retried, no side effects re-triggered.
The key is scoped to the authenticated caller (inbox for token auth, tenant for session auth), so two different callers using the same string never collide.
POST /v1/messages/,
POST /v1/contacts/,
POST /v1/calendar/events/,
POST /v1/inboxes/,
POST /v1/tokens/.
| Status | Meaning |
|---|---|
201 + X-Idempotency-Replayed: true | Key seen before — original response replayed |
| 409 | A request with this key is currently in-flight (concurrent duplicate) |
Use a deterministic key derived from your operation — for example a UUID generated once per business action and stored on your side. Keys expire after 24 hours.