Skip to content

Tenant API v1 — AI Assistant

Base path: /api/tenant/v1

Middleware: auth:tenant-api, tenant.user, not.suspended, verified, module:ai, plus Spatie permissions noted per route.

Billing: Platform mode burns wallet credits (HTTP 402 when insufficient). BYOK uses the tenant provider key and does not debit the wallet.

Permissions

PermissionPurpose
ai.useConversations, messages, credits summary, Lead Copilot
ai.confirmConfirm or cancel pending write actions
ai.manageUpdate/test workspace AI settings (PUT /settings AI keys, POST /settings/test-ai)

Credits

GET /ai/credits

Requires ai.use. Runs ensurePeriod() then returns dual-balance wallet summary and recent ledger entries.

json
{
  "included_remaining": 275,
  "prepaid_balance": 1000,
  "available": 1275,
  "period_ym": "2026-08",
  "recent_ledger": []
}

Conversations

GET /ai/conversations

List current user's conversations (newest first). Requires ai.use.

Query: limit (default 20).

POST /ai/conversations

Create a conversation. Body: optional context object (page/module hints).

GET /ai/conversations/{conversation}

Fetch conversation with messages. Scoped to the authenticated user; foreign workspace IDs → 404.

POST /ai/conversations/{conversation}/messages

Send a user message and receive structured assistant output.

Body:

json
{
  "message": "What should I focus on today?",
  "context": { "module": "tasks" }
}

Success payload includes:

  • structured.answer, structured.insights, structured.suggested_actions, structured.references
  • usage token counts and credits_burned (platform mode)
  • recent_messages (latest user + assistant turns)

Errors:

CodeWhen
402Platform wallet empty or below pre-provider credit ceiling (insufficient_ai_credits)
429AI route rate limit (throttle:ai)
503AI disabled platform-wide or module not entitled
422Validation

Pending write actions

Low-risk writes (for example create_task) create a pending row first.

POST /ai/actions/{action}/confirm

Requires ai.confirm. Executes the tool (also requires underlying domain permission, e.g. tasks.create).

POST /ai/actions/{action}/cancel

Requires ai.confirm. Marks pending action cancelled.

Lead Copilot

Requires ai.use and view policy on the lead.

MethodPathDescription
POST/ai/leads/{lead}/summarizeOne-paragraph overview + themes
POST/ai/leads/{lead}/next-actionRecommended next step
POST/ai/leads/{lead}/draft-follow-upDraft message; body channel: general | email | whatsapp

Responses mirror conversation message structured output + usage.

Agent tools (server-side)

Tools are not direct HTTP endpoints. The registry exposes them to the agent when module + permission gates pass:

Workspace (available with ai.use; per-module entitlement + view inside providers): search_workspace

Leads (leads.view / leads.update / leads.assign): search_leads, get_lead, get_stale_leads, get_recent_lead_activity, update_lead_status (pending confirmation), assign_lead (pending confirmation; assigned_to is user id or null to unassign), add_lead_note (pending confirmation; text only)

Tasks (tasks.view / tasks.create / tasks.update / tasks.assign / tasks.complete): search_tasks, get_my_tasks, get_overdue_tasks, get_tasks_due_today, get_task, create_task (pending confirmation), update_task_status (pending confirmation; visible with tasks.update or tasks.complete; complete/reopen need tasks.complete at propose+confirm; other statuses need tasks.update), assign_task (pending confirmation), add_task_note (pending confirmation; text only)

Projects (projects.view / projects.update / projects.assign): search_projects, get_project, get_overdue_projects, update_project_status (pending confirmation; requires projects.update; same as HTTP POST …/status), assign_project (pending confirmation), add_project_note (pending confirmation; text only)

Opportunities (opportunities.view / opportunities.update / opportunities.assign): search_opportunities, get_pipeline_summary, get_opportunity_stages, get_opportunity, update_opportunity_stage (pending confirmation; stage_id integer), assign_opportunity (pending confirmation), add_opportunity_note (pending confirmation; text only)

Invoices (invoices.view / invoices.update / invoices.assign / invoices.send / invoices.void): get_overdue_invoices, get_invoice_balance_summary, get_invoice, update_invoice_status (pending confirmation; visible with invoices.update or invoices.send or invoices.void; Unpaid needs send, Cancelled needs void, other targets need update at propose+confirm — same as HTTP POST …/status), assign_invoice (pending confirmation), add_invoice_note (pending confirmation; text only)

Estimates (estimates.view / estimates.update / estimates.assign / estimates.send / estimates.accept): get_estimate, update_estimate_status (pending confirmation; visible with estimates.update or send or accept; Sent needs send, Accepted needs accept, other targets need update at propose+confirm — same as HTTP POST …/status), assign_estimate (pending confirmation), add_estimate_note (pending confirmation; text only)

Quotations (quotations.view / quotations.update / quotations.assign / quotations.send / quotations.accept): get_quotation, update_quotation_status (pending confirmation; visible with quotations.update or send or accept; Sent needs send, Accepted needs accept, other targets need update at propose+confirm — same as HTTP POST …/status), assign_quotation (pending confirmation; EligibleOpportunityAssignee), add_quotation_note (pending confirmation; text only). Quotation payloads expose title (no number field).

Payments (payments.view / payments.update / payments.assign / payments.post / payments.void): get_payment, update_payment_status (pending confirmation; visible with payments.update or post or void; Posted confirm calls post(), Void confirm calls void(); Draft target rejected), assign_payment (pending confirmation), add_payment_note (pending confirmation; text only)

Credit Notes (credit-notes.view / credit-notes.update / credit-notes.assign / credit-notes.issue / credit-notes.apply / credit-notes.void / credit-notes.refund): get_credit_note, update_credit_note_status (pending confirmation; visible with credit-notes.update or issue or apply or void or refund; Issued confirm calls issue(), Applied calls apply(), Void calls void(), Refunded calls refund(); Draft target rejected), assign_credit_note (pending confirmation; EligibleCreditNoteAssignee), add_credit_note_note (pending confirmation; text only)

Purchase Orders (purchase-orders.view / purchase-orders.update / purchase-orders.assign / purchase-orders.send / purchase-orders.receive / purchase-orders.cancel): get_purchase_order, update_purchase_order_status (pending confirmation; visible with purchase-orders.update or send or receive or cancel; target-dependent auth at propose+confirm — same as HTTP POST …/status), assign_purchase_order (pending confirmation), add_purchase_order_note (pending confirmation; text only)

Help Desk (help-desk.view / help-desk.update / help-desk.assign): get_help_desk_open_tickets, get_help_desk_ticket, update_help_desk_ticket_status (pending confirmation; resolve/close also need help-desk.close at confirm), assign_help_desk_ticket (pending confirmation), add_help_desk_ticket_note (pending confirmation; text only)

Expenses (expenses.view / expenses.update / expenses.assign / expenses.submit / expenses.approve / expenses.reject / expenses.pay / expenses.cancel): get_expense_pending_approval, get_expense, update_expense_status (pending confirmation; visible with expenses.update or submit or approve or reject or pay or cancel; target-dependent auth at propose+confirm — same as HTTP POST …/status; Paid uses pay([]) so Accounting workspaces need paid_from_account_id already on the expense), assign_expense (pending confirmation), add_expense_note (pending confirmation; text only)

Leave Management (leave-management.view / leave-management.approve): get_leave_request, get_pending_leave_requests (status=pending), approve_leave_request (pending confirmation; optional review_notes / deduct_salary; notes required when overriding default salary deduction; mirrors HTTP POST …/approve; non-admins cannot approve their own request), reject_leave_request (pending confirmation; required review_notes; mirrors HTTP POST …/reject). No assign or timeline-note tools.

Tool list/detail rows expose numeric id (SPA paths) and uuid (lookups). Assignee fields use numeric assigned_to (user id) plus assignee_name when present. search_workspace hits also include path for citations; responses may list modules_failed when a provider errors without failing the whole tool. See AI tools guide.

Official documentation for the EloSync SaaS Platform.