sales:help:spec
Machine-readable API catalog, auth, errors, Agent Ledger, rate limits, and idempotency for the Sales agent.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}Generated from live external Agent API catalog metadata for SALES. Last generated at 2026-06-05T20:17:39+00:00.
sales:help:specMachine-readable API catalog, auth, errors, Agent Ledger, rate limits, and idempotency for the Sales agent.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}sales:help:openapiOpenAPI 3 YAML fragment for tools that consume OpenAPI.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}sales:help:markdownHuman-readable markdown summary of the Sales agent API (UTF-8 text/plain).
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}sales:help:guidelinesBest practices and workflows for external agents (collaboration, notes, notifications, goals/coach usage, todos list/create/complete, and pipeline health/score semantics; hints=0 on other GETs omits agent_hints).
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}sales:help:promptCanonical wrapper/system prompt snippet for external Sales agent orchestration (JSON by default; use format=text for text/plain).
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}sales:users:listList users in the subscriber tenant (max 500).
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}sales:users:createCreate a subscriber user (seat limits apply).
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)preferred_user: string (username)temp_password: stringfull_name: stringemail: stringmenu_profile_id: intsales:users:getGet one user by id (tenant-scoped).
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&user_id={id}user_id: int, requiredsales:users:updateUpdate blocked_user and/or menu_profile_id for a user in the tenant.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)user_id: int, requiredblocked_user: optional 0|1menu_profile_id: optional intsales:companies:listList CRM companies. Each row includes companies_user_id (Host), employee_count, originating_user_id and originating_date_added (immutable intake provenance when columns exist), companies_pipeline_stage, pipeline_stage_name, current_pipeline_value (SUM of companies_pipeline_data.pipeline_value; progression bar semantics like the UI), companies_temperature (Hot|Warm|Cold when column exists), companies_extra[] unless include_companies_extra=0.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&limit=100&offset=0&include_companies_extra=1&pipeline_stage_id=optionallimit: optionaloffset: optionalpipeline_stage_id: optional int filter on companies_pipeline_stageoriginating_user_id: optional int; filter prospects entered by this intake useroriginating_date_from: optional date/datetime; intake date lower boundoriginating_date_to: optional date/datetime; intake date upper bound (inclusive day)include_companies_extra: optional 0|false|off|no to omit extra query and return empty companies_extrahints: optional 0 to omit agent_hintssales:companies:getGet one company with Host (companies_user_id), employee_count, originating_user_id, originating_date_added (when columns exist), pipeline stage, current_pipeline_value, companies_extra[]. Optional include_pipeline_breakdown=1 adds pipeline_breakdown[] (per-stage rows).
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}&include_pipeline_breakdown=0|1companies_id: int, requiredinclude_companies_extra: optional 0 to omitinclude_pipeline_breakdown: optional 1 for per-stage pipeline_value rowshints: optional 0 to omit agent_hintssales:companies:createCreate a company (full subscriber onboarding: pipeline, orbits, broker). Sets originating_user_id and originating_date_added to the acting user and server time (immutable). Optional assign_to_user_id sets Host (companies_user_id) and notifies the assignee when different from acting user.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)companies_name: string, requiredcompanies_website: optional stringcompanies_main_phone: optional stringcompanies_status: optional, default Activecompanies_type: optional, default Prospectassign_to_user_id: optional int; Host / outbound owner (default acting user)assigned_broker_id: optional int (default acting user)assigned_broker_name: optional stringemployee_count: optional int >= 1 (default 1 when omitted)sales:companies:assignReassign company Host (companies_user_id) to another user. Does not change originating_user_id or originating_date_added. Notifies new Host when different from acting user.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)companies_id: int, requiredassign_to_user_id: int, requiredsales:companies:updateUpdate core company fields and optional companies_pipeline_stage (must exist in companies_stage_options when > 0). Optional companies_temperature (Hot|Warm|Cold) for manual prospect temperature when column exists.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)companies_id: int, requiredcompanies_name: optional stringcompanies_website: optional stringcompanies_main_phone: optional stringcompanies_status: optional stringcompanies_type: optional stringcompanies_pipeline_stage: optional int (companies_stage_options_id)companies_temperature: optional Hot|Warm|Coldemployee_count: optional int >= 1sales:companies:temperature_listList companies for the subscriber with a given prospect temperature. Defaults to companies owned by the acting user; optional for_user_id must be a user in the same subscriber. Each row includes pipeline fields, emails_sent_count (from note_type=email_sent when note_type exists), last_activity_at, last_inbound_note (latest inbound_* note), next_follow_up (earliest open company follow-up for that user), companies_extra[] unless include_companies_extra=0.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&temperature=Hot|Warm|Cold&for_user_id=optional&limit=100&offset=0&include_companies_extra=1temperature: required Hot|Warm|Coldfor_user_id: optional int; defaults to acting_user_idlimit: optional, max 200offset: optionalinclude_companies_extra: optional 0 to omithints: optional 0 to omit agent_hintssales:pipeline_summary:getMorning-briefing style summary for one CRM user: activity (emails sent, 7d, follow-ups, bounces, opt-outs), replies (inbound positive/negative/neutral), open company follow-up counts (overdue, due today, due in 7 days), personal user_todo counts, pipeline counts (prospects, avg pipeline value, wins, losses, hot/warm/cold company counts when temperature column exists), and canonical pipeline health/score formula fields (`avg_pipeline`, `delta_value`, `prospect_count`, `stale_count`, `penalty_per_stale`, `stale_penalty`, `pipeline_health`, `pipeline_score`). Scoped to companies assigned to that user. Requires user_notes.note_type for non-zero activity/reply metrics.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&for_user_id=optionalfor_user_id: optional int in same subscriber; defaults to acting_user_idhints: optional 0 to omit agent_hintssales:followups:listCompany-scoped open follow-ups for a user: notes on companies/contacts with an active recurring task or an open note_action_date, ordered overdue first, then due today, then due within 7 days, then future. Defaults to acting_user_id; optional for_user_id must belong to the subscriber.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&for_user_id=optional&limit=100for_user_id: optional intlimit: optional, default 100, max 200hints: optional 0 to omit agent_hintssales:followups:completeComplete one company/contact follow-up owned by the acting user. Closes user_notes.note_action_status and, when present, marks recurring_tasks.task_status completed.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)user_notes_id: int, requiredsales:pipeline_stages:listList pipeline stage definitions (companies_stage_options): id, name, order—subscriber-specific labels.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}sales:companies_extra:setSet a subscriber custom field value (companies_extra): update by companies_extra_id, or upsert by system_subscriber_companies_extra_id (insert when no row and field definition is active). Same capability as company edit on view_company.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)companies_id: int, requiredcustom_field_value: string or boolean (checkboxes: use true/false or 1/0)companies_extra_id: int, use this XOR system_subscriber_companies_extra_idsystem_subscriber_companies_extra_id: int, use this XOR companies_extra_idsales:contacts:listList contacts for a company.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}&limit=200companies_id: int, requiredsales:contacts:getGet one contact.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&contacts_id={id}contacts_id: int, requiredsales:contacts:createCreate a contact on a company; when email is provided it is stored in contacts_contact as type Email.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)companies_id: int, requiredcontacts_first_name: stringcontacts_last_name: stringcontacts_title: optional stringemail: optional string (preferred; saved to contacts_contact Email)contacts_email: optional string alias for emailsales:contacts:updateUpdate contact fields (tenant-scoped), including optional email upsert in contacts_contact.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)contacts_id: int, requiredcontacts_first_name: optional stringcontacts_last_name: optional stringcontacts_title: optional stringcontacts_status: optional stringemail: optional string (preferred; empty clears Email contact method)contacts_email: optional string alias for emailsales:contacts:findFind contacts by email (case-insensitive substring) across the tenant; returns companies_name and contacts_companies_id.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&email={address}&limit=50email: string, requiredlimit: optional max 100hints: optional 0 to omit agent_hintssales:hashtags:searchSearch CRM records by note hashtag token (same hashtag behavior humans use in companies_list hashtag links). Accepts hashtag=tag or hashtag=#tag and returns grouped companies/contacts/quotes/notes.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&hashtag={tag}&entity=all|companies|contacts|quotes|notes&limit=50&offset=0hashtag: required string hashtag token, with or without leading #entity: optional all|companies|contacts|quotes|notes (default all)limit: optional int, default 50, max 200offset: optional int, default 0hints: optional 0 to omit agent_hintssales:company_email_log:listList structured email-activity rows for a company. Returns HTTP 501 not_configured with a hint if table companies_email_exchange is missing—apply migrations/add_companies_email_exchange.sql first.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}&limit=50companies_id: int, requiredlimit: optionalhints: optional 0 to omit agent_hintssales:company_email_log:createCreate a structured email log entry on a company. Inbound rows (direction=in) can auto-classify reply sentiment, write note_type telemetry, and auto-update companies_temperature with dedupe by message_id + tenant and cooldown protection for recent manual overrides.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)companies_id: int, requireddirection: in|out, requiredsummary: string, requiredsubject: optional string (max 500)occurred_at: optional datetime (default now)message_id: optional stringauto_track_inbound_reply: optional bool; default true when direction=inreply_classification: optional positive|neutral|negative|inbound_positive|inbound_neutral|inbound_negativeauto_update_temperature: optional bool; default truemanual_override_cooldown_hours: optional int 0..168 (default from feature toggle, fallback 24)force_temperature_update: optional bool to bypass cooldown guardsales:notes:createAdd a note on a company or contact. Optional is_recurring creates recurring_tasks (same as view_company “Make this a task”). Optional note_type classifies activity (email_sent, follow_up_sent, inbound_positive, bounce, opt_out, etc.); inbound_positive sets company temperature Hot and inbound_negative sets Cold when companies_temperature exists (neutral/other types do not auto-change temperature).
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)notes_table: companies|contactscompanies_id: int (required if notes_table=companies)contacts_id: int (required if notes_table=contacts)user_note: stringnote_view: internal|external, default internalinclude_ai: optional 0|1 (subscriber Gmail/email knowledge when 1)note_type: optional closed vocabulary; see help:guidelines sales note_type listis_recurring: optional truthy to add recurring_tasksrecurrence_type: required when is_recurring: once|daily|weekly|monthly (omit or empty defaults to once)first_occurrence: optional datetime string (default now)end_date: optionaloccurrence_limit: optional int, default 1sales:notes:getGet one company-scoped note by user_notes_id (tenant-safe).
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&user_notes_id={id}user_notes_id: int, requiredsales:notes:listList notes for the tenant; optional companies_id scopes to one company (same as sales:records:read&entity=notes).
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={optional}&limit=500companies_id: optional intlimit: optional, default 500, max 500sales:records:readSales agent: read CRM entities. entity=companies includes Host (companies_user_id), employee_count, originating_user_id, originating_date_added when columns exist, pipeline stage, current_pipeline_value, companies_temperature when present, companies_extra[] unless include_companies_extra=0. Optional originating_user_id and originating_date_from/to filters on entity=companies. entity=notes includes note_type when present. entity=contacts supports email= substring filter and returns email, companies_name when set.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&entity=companies|contacts|notes|tasks&companies_id=optional&limit=500entity: companies|contacts|notes|taskscompanies_id: optional filter when entity=notesoriginating_user_id: optional when entity=companiesoriginating_date_from: optional when entity=companiesoriginating_date_to: optional when entity=companiesemail: optional when entity=contacts (case-insensitive search)limit: optionalinclude_companies_extra: optional 0 when entity=companies to omit custom fieldshints: optional 0 to omit agent_hintssales:notifications:listOpen in-app notifications for the acting user plus due/overdue personal task counts (nav parity). Product review request notifications can include review_request context and one_tap submit payloads.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}sales:notifications:dismissMark a notification as read (open_closed=1) for the acting user.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)users_notifications_id: int, requiredsales:todos:listList personal to-dos (user_todo) for the acting user; same source as My To-Do List.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&status=all|open|closed&limit=100status: optional open|closed|all, default alllimit: optional int, default 100, max 200hints: optional 0 to omit agent_hintssales:todos:createAdd a personal to-do (user_todo) for the acting user.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)todo_text: string, requireddue_date: YYYY-MM-DD, requiredsales:todos:completeMark a personal to-do complete (must be owned by acting user).
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)user_notes_id: int, requiredsales:product_updates:listSubscriber-visible What's New entries (published, not internal-only).
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&limit=20&since_date=YYYY-MM-DD&after_id=0limit: optional int, default 20, max 100since_date: optional, filter update_date >= dateafter_id: optional int, filter quote_rocket_update_id > idsales:product_reviews:createCapture a product review from an external Sales AI principal (1-5 rating + review text). Stores acting user/subscriber context plus optional model/provider metadata.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)rating: int 1..5, requiredreview_text: string, requiredheadline: optional stringwould_recommend: optional booleancompanies_id: optional intcontacts_id: optional intsource: optional stringreviewer_name: optional stringreviewer_email: optional stringagent_provider: optional stringagent_model: optional stringagent_run_id: optional stringagent_identity_label: optional stringsales:product_reviews:listList captured product reviews for the tenant (paginated).
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&limit=50&offset=0&companies_id=optional&agent_type=optionallimit: optional int, default 50, max 200offset: optional int, default 0companies_id: optional intagent_type: optional sales|servicehints: optional 0 to omit agent_hintssales:feature_feedback:createCapture enhancement feedback from external Sales AI principals when a feature does not meet their exact needs.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)title: string, requireddetails: string, requiredfeedback_type: optional improvement|bug|request|ux|other (default improvement)priority: optional low|normal|high|critical (default normal)feature_key: optional stringcompanies_id: optional intcontacts_id: optional intsource: optional stringagent_provider: optional stringagent_model: optional stringagent_run_id: optional stringagent_identity_label: optional stringsales:feature_feedback:listList feature feedback captured from external agents (paginated).
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&limit=50&offset=0&feedback_type=optional&priority=optionallimit: optional int, default 50, max 200offset: optional int, default 0feedback_type: optional improvement|bug|request|ux|otherpriority: optional low|normal|high|criticalhints: optional 0 to omit agent_hintssales:goals:getGet goal settings for the acting user (or optional same-tenant for_user_id). Returns core and migrated goal columns when present.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&for_user_id=optionalfor_user_id: optional int in same subscriber; defaults to acting_user_idhints: optional 0 to omit agent_hintssales:goals:updateUpdate one or more goal fields for the acting user (or optional same-tenant for_user_id). Supports base goals and optional migrated goal columns.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)for_user_id: optional int in same subscriber; defaults to acting_user_idgoals: object keyed by goal field names (recommended)total_clients_goal: optional int >= 0monthly_clients_goal: optional int >= 0total_prospects_goal: optional int >= 0monthly_prospects_goal: optional int >= 0total_quotes_goal: optional int >= 0 when column existsmonthly_quotes_goal: optional int >= 0 when column existsconsistency_goal_pct: optional number clamped 0..100 when column existsclient_retention_goal_pct: optional number clamped 0..100 when column existsavg_underwriting_time_goal: optional int >= 0 when column existsclient_stability_goal_days: optional int >= 0 when column existssales:coach:getGet Personal Coach settings for acting user or optional same-tenant for_user_id. Requires personal_coach entitlement.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&for_user_id=optionalfor_user_id: optional int in same subscriber; defaults to acting_user_idhints: optional 0 to omit agent_hintssales:coach:updateUpdate Personal Coach enabled/frequency/day for acting user or optional same-tenant for_user_id. Requires personal_coach entitlement. External machine users are forced to enabled + bi_weekly + Monday defaults.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)for_user_id: optional int in same subscriber; defaults to acting_user_idenabled: optional 0|1 (ignored for external_machine_agent; forced to 1)report_frequency: required weekly|bi_weekly|semi_monthly|monthly (forced bi_weekly for external_machine_agent)report_day_of_week: required int 0..6 (forced 1 Monday for external_machine_agent)sales:quotes:listList payroll proposals (quotes) for the tenant via company scope.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&limit=50&offset=0sales:quotes:getGet one payroll proposal by id.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&payroll_proposal_id={id}payroll_proposal_id: int, requiredsales:enrollment_customers:listList customer portal accounts for one company.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}companies_id: int, requiredsales:enrollment_customers:createInvite/create a customer portal account.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)companies_id: int, requiredemail: string, requiredfull_name: string, requiredtemp_password: optional stringsales:enrollment_customers:updateUpdate customer portal account status (active|disabled).
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)companies_id: int, requiredportal_customer_id: int, requiredstatus: string, requiredsales:enrollment_customers:reset_passwordReset customer portal password and return a temporary password.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)companies_id: int, requiredportal_customer_id: int, requiredtemp_password: optional stringsales:enrollment_documents:listList enrollment documents.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}&limit=200companies_id: int, requiredlimit: optional intsales:enrollment_documents:createCreate enrollment document metadata record.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)companies_id: int, requireddocument_name: string, requireddocument_category: optional stringdocument_status: optional stringfile_path: string, requiredfile_size_bytes: optional intmime_type: optional stringrequires_signature: optional boolsales:enrollment_employees:listList employee roster records for enrollment.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}companies_id: int, requiredsales:enrollment_employees:upsertCreate or update an enrollment employee row.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)companies_id: int, requiredportal_employee_id: optional int for updateemployee_first_name: string, requiredemployee_last_name: string, requiredemployee_email: optional stringemployee_title: optional stringenrollment_status: optional stringonboarding_step: optional stringsales:enrollment_notes:listList enrollment notes.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}&limit=200companies_id: int, requiredlimit: optional intsales:enrollment_notes:createCreate an enrollment note.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)companies_id: int, requirednote_body: string, requiredvisibility: optional shared|subscriber_onlysales:enrollment_tasks:listList enrollment tasks and approvals.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}companies_id: int, requiredsales:enrollment_tasks:createCreate an enrollment task.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)companies_id: int, requiredtask_title: string, requiredtask_details: optional stringtask_status: optional stringdue_date: optional YYYY-MM-DDassigned_to_type: optional customer|subscriberassigned_to_user_id: optional intassigned_to_customer_id: optional intrequires_approval: optional boolsales:enrollment_tasks:updateUpdate enrollment task status.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)companies_id: int, requiredportal_task_id: int, requiredtask_status: string, requiredsales:enrollment_signatures:listList enrollment signature requests and outcomes.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}companies_id: int, requiredsales:enrollment_signatures:createRequest a new enrollment signature.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)companies_id: int, requiredportal_document_id: int, requiredsigner_name: string, requiredsigner_email: string, requiredsales:enrollment_signatures:signApply a signature to a requested enrollment signature.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)companies_id: int, requiredportal_signature_id: int, requiredsignature_value: string, requiredsales:enrollment_notifications:listList enrollment notifications for a customer or company.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}&portal_customer_id=optionalcompanies_id: int, requiredportal_customer_id: optional intsales:enrollment_notifications:dismissMark one enrollment notification as read.
POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)companies_id: int, requiredportal_customer_id: optional intportal_notification_id: int, requiredsales:enrollment_timeline:listList enrollment timeline audit events.
GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}&limit=300companies_id: int, requiredlimit: optional intopenapi: 3.0.3
info:
title: Quote Rocket Agent API
version: 1.0.0
description: "All HTTP calls are GET or POST to this entrypoint URL with required query parameters agent, resource, and action. POST keeps those params in the URL; JSON body is only for input fields, not routing. Path keys in this file are logical groupings; call the entrypoint with matching query params."
servers:
- url: "https://quoterocket.ai/shr/agent_api_router.php"
paths:
"/sales/help/spec":
get:
operationId: sales_help_spec
summary: "Machine-readable API catalog, auth, errors, Agent Ledger, rate limits, and idempotency for the Sales agent."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "help"
- name: action
in: query
required: true
schema:
type: string
default: "spec"
responses:
'200':
description: OK
'201':
description: Created
"/sales/help/openapi":
get:
operationId: sales_help_openapi
summary: "OpenAPI 3 YAML fragment for tools that consume OpenAPI."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "help"
- name: action
in: query
required: true
schema:
type: string
default: "openapi"
responses:
'200':
description: OK
'201':
description: Created
"/sales/help/markdown":
get:
operationId: sales_help_markdown
summary: "Human-readable markdown summary of the Sales agent API (UTF-8 text\/plain)."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "help"
- name: action
in: query
required: true
schema:
type: string
default: "markdown"
responses:
'200':
description: OK
'201':
description: Created
"/sales/help/guidelines":
get:
operationId: sales_help_guidelines
summary: "Best practices and workflows for external agents (collaboration, notes, notifications, goals\/coach usage, todos list\/create\/complete, and pipeline health\/score semantics; hints=0 on other GETs omits agent_hints)."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "help"
- name: action
in: query
required: true
schema:
type: string
default: "guidelines"
responses:
'200':
description: OK
'201':
description: Created
"/sales/help/prompt":
get:
operationId: sales_help_prompt
summary: "Canonical wrapper\/system prompt snippet for external Sales agent orchestration (JSON by default; use format=text for text\/plain)."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "help"
- name: action
in: query
required: true
schema:
type: string
default: "prompt"
responses:
'200':
description: OK
'201':
description: Created
"/sales/users/list":
get:
operationId: sales_users_list
summary: "List users in the subscriber tenant (max 500)."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "users"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/users/create":
post:
operationId: sales_users_create
summary: "Create a subscriber user (seat limits apply)."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "users"
- name: action
in: query
required: true
schema:
type: string
default: "create"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/users/get":
get:
operationId: sales_users_get
summary: "Get one user by id (tenant-scoped)."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "users"
- name: action
in: query
required: true
schema:
type: string
default: "get"
responses:
'200':
description: OK
'201':
description: Created
"/sales/users/update":
post:
operationId: sales_users_update
summary: "Update blocked_user and\/or menu_profile_id for a user in the tenant."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "users"
- name: action
in: query
required: true
schema:
type: string
default: "update"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/companies/list":
get:
operationId: sales_companies_list
summary: "List CRM companies. Each row includes companies_user_id (Host), employee_count, originating_user_id and originating_date_added (immutable intake provenance when columns exist), companies_pipeline_stage, pipeline_stage_name, current_pipeline_value (SUM of companies_pipeline_data.pipeline_value; progression bar semantics like the UI), companies_temperature (Hot|Warm|Cold when column exists), companies_extra[] unless include_companies_extra=0."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "companies"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/companies/get":
get:
operationId: sales_companies_get
summary: "Get one company with Host (companies_user_id), employee_count, originating_user_id, originating_date_added (when columns exist), pipeline stage, current_pipeline_value, companies_extra[]. Optional include_pipeline_breakdown=1 adds pipeline_breakdown[] (per-stage rows)."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "companies"
- name: action
in: query
required: true
schema:
type: string
default: "get"
responses:
'200':
description: OK
'201':
description: Created
"/sales/companies/create":
post:
operationId: sales_companies_create
summary: "Create a company (full subscriber onboarding: pipeline, orbits, broker). Sets originating_user_id and originating_date_added to the acting user and server time (immutable). Optional assign_to_user_id sets Host (companies_user_id) and notifies the assignee when different from acting user."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "companies"
- name: action
in: query
required: true
schema:
type: string
default: "create"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/companies/assign":
post:
operationId: sales_companies_assign
summary: "Reassign company Host (companies_user_id) to another user. Does not change originating_user_id or originating_date_added. Notifies new Host when different from acting user."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "companies"
- name: action
in: query
required: true
schema:
type: string
default: "assign"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/companies/update":
post:
operationId: sales_companies_update
summary: "Update core company fields and optional companies_pipeline_stage (must exist in companies_stage_options when > 0). Optional companies_temperature (Hot|Warm|Cold) for manual prospect temperature when column exists."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "companies"
- name: action
in: query
required: true
schema:
type: string
default: "update"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/companies/temperature_list":
get:
operationId: sales_companies_temperature_list
summary: "List companies for the subscriber with a given prospect temperature. Defaults to companies owned by the acting user; optional for_user_id must be a user in the same subscriber. Each row includes pipeline fields, emails_sent_count (from note_type=email_sent when note_type exists), last_activity_at, last_inbound_note (latest inbound_* note), next_follow_up (earliest open company follow-up for that user), companies_extra[] unless include_companies_extra=0."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "companies"
- name: action
in: query
required: true
schema:
type: string
default: "temperature_list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/pipeline_summary/get":
get:
operationId: sales_pipeline_summary_get
summary: "Morning-briefing style summary for one CRM user: activity (emails sent, 7d, follow-ups, bounces, opt-outs), replies (inbound positive\/negative\/neutral), open company follow-up counts (overdue, due today, due in 7 days), personal user_todo counts, pipeline counts (prospects, avg pipeline value, wins, losses, hot\/warm\/cold company counts when temperature column exists), and canonical pipeline health\/score formula fields (`avg_pipeline`, `delta_value`, `prospect_count`, `stale_count`, `penalty_per_stale`, `stale_penalty`, `pipeline_health`, `pipeline_score`). Scoped to companies assigned to that user. Requires user_notes.note_type for non-zero activity\/reply metrics."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "pipeline_summary"
- name: action
in: query
required: true
schema:
type: string
default: "get"
responses:
'200':
description: OK
'201':
description: Created
"/sales/followups/list":
get:
operationId: sales_followups_list
summary: "Company-scoped open follow-ups for a user: notes on companies\/contacts with an active recurring task or an open note_action_date, ordered overdue first, then due today, then due within 7 days, then future. Defaults to acting_user_id; optional for_user_id must belong to the subscriber."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "followups"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/followups/complete":
post:
operationId: sales_followups_complete
summary: "Complete one company\/contact follow-up owned by the acting user. Closes user_notes.note_action_status and, when present, marks recurring_tasks.task_status completed."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "followups"
- name: action
in: query
required: true
schema:
type: string
default: "complete"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/pipeline_stages/list":
get:
operationId: sales_pipeline_stages_list
summary: "List pipeline stage definitions (companies_stage_options): id, name, order—subscriber-specific labels."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "pipeline_stages"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/companies_extra/set":
post:
operationId: sales_companies_extra_set
summary: "Set a subscriber custom field value (companies_extra): update by companies_extra_id, or upsert by system_subscriber_companies_extra_id (insert when no row and field definition is active). Same capability as company edit on view_company."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "companies_extra"
- name: action
in: query
required: true
schema:
type: string
default: "set"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/contacts/list":
get:
operationId: sales_contacts_list
summary: "List contacts for a company."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "contacts"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/contacts/get":
get:
operationId: sales_contacts_get
summary: "Get one contact."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "contacts"
- name: action
in: query
required: true
schema:
type: string
default: "get"
responses:
'200':
description: OK
'201':
description: Created
"/sales/contacts/create":
post:
operationId: sales_contacts_create
summary: "Create a contact on a company; when email is provided it is stored in contacts_contact as type Email."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "contacts"
- name: action
in: query
required: true
schema:
type: string
default: "create"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/contacts/update":
post:
operationId: sales_contacts_update
summary: "Update contact fields (tenant-scoped), including optional email upsert in contacts_contact."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "contacts"
- name: action
in: query
required: true
schema:
type: string
default: "update"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/contacts/find":
get:
operationId: sales_contacts_find
summary: "Find contacts by email (case-insensitive substring) across the tenant; returns companies_name and contacts_companies_id."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "contacts"
- name: action
in: query
required: true
schema:
type: string
default: "find"
responses:
'200':
description: OK
'201':
description: Created
"/sales/hashtags/search":
get:
operationId: sales_hashtags_search
summary: "Search CRM records by note hashtag token (same hashtag behavior humans use in companies_list hashtag links). Accepts hashtag=tag or hashtag=#tag and returns grouped companies\/contacts\/quotes\/notes."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "hashtags"
- name: action
in: query
required: true
schema:
type: string
default: "search"
responses:
'200':
description: OK
'201':
description: Created
"/sales/company_email_log/list":
get:
operationId: sales_company_email_log_list
summary: "List structured email-activity rows for a company. Returns HTTP 501 not_configured with a hint if table companies_email_exchange is missing—apply migrations\/add_companies_email_exchange.sql first."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "company_email_log"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/company_email_log/create":
post:
operationId: sales_company_email_log_create
summary: "Create a structured email log entry on a company. Inbound rows (direction=in) can auto-classify reply sentiment, write note_type telemetry, and auto-update companies_temperature with dedupe by message_id + tenant and cooldown protection for recent manual overrides."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "company_email_log"
- name: action
in: query
required: true
schema:
type: string
default: "create"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/notes/create":
post:
operationId: sales_notes_create
summary: "Add a note on a company or contact. Optional is_recurring creates recurring_tasks (same as view_company “Make this a task”). Optional note_type classifies activity (email_sent, follow_up_sent, inbound_positive, bounce, opt_out, etc.); inbound_positive sets company temperature Hot and inbound_negative sets Cold when companies_temperature exists (neutral\/other types do not auto-change temperature)."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "notes"
- name: action
in: query
required: true
schema:
type: string
default: "create"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/notes/get":
get:
operationId: sales_notes_get
summary: "Get one company-scoped note by user_notes_id (tenant-safe)."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "notes"
- name: action
in: query
required: true
schema:
type: string
default: "get"
responses:
'200':
description: OK
'201':
description: Created
"/sales/notes/list":
get:
operationId: sales_notes_list
summary: "List notes for the tenant; optional companies_id scopes to one company (same as sales:records:read&entity=notes)."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "notes"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/records/read":
get:
operationId: sales_records_read
summary: "Sales agent: read CRM entities. entity=companies includes Host (companies_user_id), employee_count, originating_user_id, originating_date_added when columns exist, pipeline stage, current_pipeline_value, companies_temperature when present, companies_extra[] unless include_companies_extra=0. Optional originating_user_id and originating_date_from\/to filters on entity=companies. entity=notes includes note_type when present. entity=contacts supports email= substring filter and returns email, companies_name when set."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "records"
- name: action
in: query
required: true
schema:
type: string
default: "read"
responses:
'200':
description: OK
'201':
description: Created
"/sales/notifications/list":
get:
operationId: sales_notifications_list
summary: "Open in-app notifications for the acting user plus due\/overdue personal task counts (nav parity). Product review request notifications can include review_request context and one_tap submit payloads."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "notifications"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/notifications/dismiss":
post:
operationId: sales_notifications_dismiss
summary: "Mark a notification as read (open_closed=1) for the acting user."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "notifications"
- name: action
in: query
required: true
schema:
type: string
default: "dismiss"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/todos/list":
get:
operationId: sales_todos_list
summary: "List personal to-dos (user_todo) for the acting user; same source as My To-Do List."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "todos"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/todos/create":
post:
operationId: sales_todos_create
summary: "Add a personal to-do (user_todo) for the acting user."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "todos"
- name: action
in: query
required: true
schema:
type: string
default: "create"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/todos/complete":
post:
operationId: sales_todos_complete
summary: "Mark a personal to-do complete (must be owned by acting user)."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "todos"
- name: action
in: query
required: true
schema:
type: string
default: "complete"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/product_updates/list":
get:
operationId: sales_product_updates_list
summary: "Subscriber-visible What's New entries (published, not internal-only)."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "product_updates"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/product_reviews/create":
post:
operationId: sales_product_reviews_create
summary: "Capture a product review from an external Sales AI principal (1-5 rating + review text). Stores acting user\/subscriber context plus optional model\/provider metadata."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "product_reviews"
- name: action
in: query
required: true
schema:
type: string
default: "create"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/product_reviews/list":
get:
operationId: sales_product_reviews_list
summary: "List captured product reviews for the tenant (paginated)."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "product_reviews"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/feature_feedback/create":
post:
operationId: sales_feature_feedback_create
summary: "Capture enhancement feedback from external Sales AI principals when a feature does not meet their exact needs."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "feature_feedback"
- name: action
in: query
required: true
schema:
type: string
default: "create"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/feature_feedback/list":
get:
operationId: sales_feature_feedback_list
summary: "List feature feedback captured from external agents (paginated)."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "feature_feedback"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/goals/get":
get:
operationId: sales_goals_get
summary: "Get goal settings for the acting user (or optional same-tenant for_user_id). Returns core and migrated goal columns when present."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "goals"
- name: action
in: query
required: true
schema:
type: string
default: "get"
responses:
'200':
description: OK
'201':
description: Created
"/sales/goals/update":
post:
operationId: sales_goals_update
summary: "Update one or more goal fields for the acting user (or optional same-tenant for_user_id). Supports base goals and optional migrated goal columns."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "goals"
- name: action
in: query
required: true
schema:
type: string
default: "update"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/coach/get":
get:
operationId: sales_coach_get
summary: "Get Personal Coach settings for acting user or optional same-tenant for_user_id. Requires personal_coach entitlement."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "coach"
- name: action
in: query
required: true
schema:
type: string
default: "get"
responses:
'200':
description: OK
'201':
description: Created
"/sales/coach/update":
post:
operationId: sales_coach_update
summary: "Update Personal Coach enabled\/frequency\/day for acting user or optional same-tenant for_user_id. Requires personal_coach entitlement. External machine users are forced to enabled + bi_weekly + Monday defaults."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "coach"
- name: action
in: query
required: true
schema:
type: string
default: "update"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/quotes/list":
get:
operationId: sales_quotes_list
summary: "List payroll proposals (quotes) for the tenant via company scope."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "quotes"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/quotes/get":
get:
operationId: sales_quotes_get
summary: "Get one payroll proposal by id."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "quotes"
- name: action
in: query
required: true
schema:
type: string
default: "get"
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_customers/list":
get:
operationId: sales_enrollment_customers_list
summary: "List customer portal accounts for one company."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_customers"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_customers/create":
post:
operationId: sales_enrollment_customers_create
summary: "Invite\/create a customer portal account."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_customers"
- name: action
in: query
required: true
schema:
type: string
default: "create"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_customers/update":
post:
operationId: sales_enrollment_customers_update
summary: "Update customer portal account status (active|disabled)."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_customers"
- name: action
in: query
required: true
schema:
type: string
default: "update"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_customers/reset_password":
post:
operationId: sales_enrollment_customers_reset_password
summary: "Reset customer portal password and return a temporary password."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_customers"
- name: action
in: query
required: true
schema:
type: string
default: "reset_password"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_documents/list":
get:
operationId: sales_enrollment_documents_list
summary: "List enrollment documents."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_documents"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_documents/create":
post:
operationId: sales_enrollment_documents_create
summary: "Create enrollment document metadata record."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_documents"
- name: action
in: query
required: true
schema:
type: string
default: "create"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_employees/list":
get:
operationId: sales_enrollment_employees_list
summary: "List employee roster records for enrollment."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_employees"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_employees/upsert":
post:
operationId: sales_enrollment_employees_upsert
summary: "Create or update an enrollment employee row."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_employees"
- name: action
in: query
required: true
schema:
type: string
default: "upsert"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_notes/list":
get:
operationId: sales_enrollment_notes_list
summary: "List enrollment notes."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_notes"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_notes/create":
post:
operationId: sales_enrollment_notes_create
summary: "Create an enrollment note."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_notes"
- name: action
in: query
required: true
schema:
type: string
default: "create"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_tasks/list":
get:
operationId: sales_enrollment_tasks_list
summary: "List enrollment tasks and approvals."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_tasks"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_tasks/create":
post:
operationId: sales_enrollment_tasks_create
summary: "Create an enrollment task."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_tasks"
- name: action
in: query
required: true
schema:
type: string
default: "create"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_tasks/update":
post:
operationId: sales_enrollment_tasks_update
summary: "Update enrollment task status."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_tasks"
- name: action
in: query
required: true
schema:
type: string
default: "update"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_signatures/list":
get:
operationId: sales_enrollment_signatures_list
summary: "List enrollment signature requests and outcomes."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_signatures"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_signatures/create":
post:
operationId: sales_enrollment_signatures_create
summary: "Request a new enrollment signature."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_signatures"
- name: action
in: query
required: true
schema:
type: string
default: "create"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_signatures/sign":
post:
operationId: sales_enrollment_signatures_sign
summary: "Apply a signature to a requested enrollment signature."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_signatures"
- name: action
in: query
required: true
schema:
type: string
default: "sign"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_notifications/list":
get:
operationId: sales_enrollment_notifications_list
summary: "List enrollment notifications for a customer or company."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_notifications"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_notifications/dismiss":
post:
operationId: sales_enrollment_notifications_dismiss
summary: "Mark one enrollment notification as read."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_notifications"
- name: action
in: query
required: true
schema:
type: string
default: "dismiss"
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: OK
'201':
description: Created
"/sales/enrollment_timeline/list":
get:
operationId: sales_enrollment_timeline_list
summary: "List enrollment timeline audit events."
parameters:
- name: agent
in: query
required: true
schema:
type: string
enum: [sales]
- name: resource
in: query
required: true
schema:
type: string
default: "enrollment_timeline"
- name: action
in: query
required: true
schema:
type: string
default: "list"
responses:
'200':
description: OK
'201':
description: Created
# Quote Rocket Agent API (sales)
**Agent Ledger:** every call is audited with a human-readable line. Use `request_id` from responses.
## Authentication
- `Authorization: Bearer <api_key>` or `X-API-Key: <api_key>`
- Principal includes `acting_user_id` for menu parity.
## Entry URL (required for every call)
**Always** append `agent`, `resource`, and `action` as query parameters on `agent_api_router.php` — including **POST**. Do not send only a JSON body to the bare entrypoint; that returns `route_not_found`.
`https://quoterocket.ai/shr/agent_api_router.php?agent=sales&resource=...&action=...`
## Best practices (external agents)
- Full document: `sales:help:guidelines` (GET same entry URL with `resource=help&action=guidelines`).
- When humans address you in Quote Rocket, add a **note on the company or contact** via the API so the conversation stays in CRM.
- Use **notifications:list** / **notifications:dismiss**, **todos:list** / **todos:create** / **todos:complete**, and **product_updates:list** as designed in the UI.
- Most GET JSON responses include an **agent_hints** object; pass **hints=0** to omit it.
## Routes
### `sales:help:spec`
- **Method:** GET
- **Capability:** `sales.help.read`
- **Description:** Machine-readable API catalog, auth, errors, Agent Ledger, rate limits, and idempotency for the Sales agent.
### `sales:help:openapi`
- **Method:** GET
- **Capability:** `sales.help.read`
- **Description:** OpenAPI 3 YAML fragment for tools that consume OpenAPI.
### `sales:help:markdown`
- **Method:** GET
- **Capability:** `sales.help.read`
- **Description:** Human-readable markdown summary of the Sales agent API (UTF-8 text/plain).
### `sales:help:guidelines`
- **Method:** GET
- **Capability:** `sales.help.read`
- **Description:** Best practices and workflows for external agents (collaboration, notes, notifications, goals/coach usage, todos list/create/complete, and pipeline health/score semantics; hints=0 on other GETs omits agent_hints).
### `sales:help:prompt`
- **Method:** GET
- **Capability:** `sales.help.read`
- **Description:** Canonical wrapper/system prompt snippet for external Sales agent orchestration (JSON by default; use format=text for text/plain).
### `sales:users:list`
- **Method:** GET
- **Capability:** `sales.users.read`
- **Description:** List users in the subscriber tenant (max 500).
### `sales:users:create`
- **Method:** POST
- **Capability:** `sales.users.create`
- **Description:** Create a subscriber user (seat limits apply).
- **JSON body:**
- `preferred_user`: string (username)
- `temp_password`: string
- `full_name`: string
- `email`: string
- `menu_profile_id`: int
### `sales:users:get`
- **Method:** GET
- **Capability:** `sales.users.read`
- **Description:** Get one user by id (tenant-scoped).
- **Query:**
- `user_id`: int, required
### `sales:users:update`
- **Method:** POST
- **Capability:** `sales.users.update`
- **Description:** Update blocked_user and/or menu_profile_id for a user in the tenant.
- **JSON body:**
- `user_id`: int, required
- `blocked_user`: optional 0|1
- `menu_profile_id`: optional int
### `sales:companies:list`
- **Method:** GET
- **Capability:** `sales.companies.read`
- **Description:** List CRM companies. Each row includes companies_user_id (Host), employee_count, originating_user_id and originating_date_added (immutable intake provenance when columns exist), companies_pipeline_stage, pipeline_stage_name, current_pipeline_value (SUM of companies_pipeline_data.pipeline_value; progression bar semantics like the UI), companies_temperature (Hot|Warm|Cold when column exists), companies_extra[] unless include_companies_extra=0.
- **Query:**
- `limit`: optional
- `offset`: optional
- `pipeline_stage_id`: optional int filter on companies_pipeline_stage
- `originating_user_id`: optional int; filter prospects entered by this intake user
- `originating_date_from`: optional date/datetime; intake date lower bound
- `originating_date_to`: optional date/datetime; intake date upper bound (inclusive day)
- `include_companies_extra`: optional 0|false|off|no to omit extra query and return empty companies_extra
- `hints`: optional 0 to omit agent_hints
### `sales:companies:get`
- **Method:** GET
- **Capability:** `sales.companies.read`
- **Description:** Get one company with Host (companies_user_id), employee_count, originating_user_id, originating_date_added (when columns exist), pipeline stage, current_pipeline_value, companies_extra[]. Optional include_pipeline_breakdown=1 adds pipeline_breakdown[] (per-stage rows).
- **Query:**
- `companies_id`: int, required
- `include_companies_extra`: optional 0 to omit
- `include_pipeline_breakdown`: optional 1 for per-stage pipeline_value rows
- `hints`: optional 0 to omit agent_hints
### `sales:companies:create`
- **Method:** POST
- **Capability:** `sales.companies.create`
- **Description:** Create a company (full subscriber onboarding: pipeline, orbits, broker). Sets originating_user_id and originating_date_added to the acting user and server time (immutable). Optional assign_to_user_id sets Host (companies_user_id) and notifies the assignee when different from acting user.
- **JSON body:**
- `companies_name`: string, required
- `companies_website`: optional string
- `companies_main_phone`: optional string
- `companies_status`: optional, default Active
- `companies_type`: optional, default Prospect
- `assign_to_user_id`: optional int; Host / outbound owner (default acting user)
- `assigned_broker_id`: optional int (default acting user)
- `assigned_broker_name`: optional string
- `employee_count`: optional int >= 1 (default 1 when omitted)
### `sales:companies:assign`
- **Method:** POST
- **Capability:** `sales.companies.update`
- **Description:** Reassign company Host (companies_user_id) to another user. Does not change originating_user_id or originating_date_added. Notifies new Host when different from acting user.
- **JSON body:**
- `companies_id`: int, required
- `assign_to_user_id`: int, required
### `sales:companies:update`
- **Method:** POST
- **Capability:** `sales.companies.update`
- **Description:** Update core company fields and optional companies_pipeline_stage (must exist in companies_stage_options when > 0). Optional companies_temperature (Hot|Warm|Cold) for manual prospect temperature when column exists.
- **JSON body:**
- `companies_id`: int, required
- `companies_name`: optional string
- `companies_website`: optional string
- `companies_main_phone`: optional string
- `companies_status`: optional string
- `companies_type`: optional string
- `companies_pipeline_stage`: optional int (companies_stage_options_id)
- `companies_temperature`: optional Hot|Warm|Cold
- `employee_count`: optional int >= 1
### `sales:companies:temperature_list`
- **Method:** GET
- **Capability:** `sales.companies.read`
- **Description:** List companies for the subscriber with a given prospect temperature. Defaults to companies owned by the acting user; optional for_user_id must be a user in the same subscriber. Each row includes pipeline fields, emails_sent_count (from note_type=email_sent when note_type exists), last_activity_at, last_inbound_note (latest inbound_* note), next_follow_up (earliest open company follow-up for that user), companies_extra[] unless include_companies_extra=0.
- **Query:**
- `temperature`: required Hot|Warm|Cold
- `for_user_id`: optional int; defaults to acting_user_id
- `limit`: optional, max 200
- `offset`: optional
- `include_companies_extra`: optional 0 to omit
- `hints`: optional 0 to omit agent_hints
### `sales:pipeline_summary:get`
- **Method:** GET
- **Capability:** `sales.companies.read`
- **Description:** Morning-briefing style summary for one CRM user: activity (emails sent, 7d, follow-ups, bounces, opt-outs), replies (inbound positive/negative/neutral), open company follow-up counts (overdue, due today, due in 7 days), personal user_todo counts, pipeline counts (prospects, avg pipeline value, wins, losses, hot/warm/cold company counts when temperature column exists), and canonical pipeline health/score formula fields (`avg_pipeline`, `delta_value`, `prospect_count`, `stale_count`, `penalty_per_stale`, `stale_penalty`, `pipeline_health`, `pipeline_score`). Scoped to companies assigned to that user. Requires user_notes.note_type for non-zero activity/reply metrics.
- **Query:**
- `for_user_id`: optional int in same subscriber; defaults to acting_user_id
- `hints`: optional 0 to omit agent_hints
### `sales:followups:list`
- **Method:** GET
- **Capability:** `sales.notes.read`
- **Description:** Company-scoped open follow-ups for a user: notes on companies/contacts with an active recurring task or an open note_action_date, ordered overdue first, then due today, then due within 7 days, then future. Defaults to acting_user_id; optional for_user_id must belong to the subscriber.
- **Query:**
- `for_user_id`: optional int
- `limit`: optional, default 100, max 200
- `hints`: optional 0 to omit agent_hints
### `sales:followups:complete`
- **Method:** POST
- **Capability:** `sales.notes.create`
- **Description:** Complete one company/contact follow-up owned by the acting user. Closes user_notes.note_action_status and, when present, marks recurring_tasks.task_status completed.
- **JSON body:**
- `user_notes_id`: int, required
### `sales:pipeline_stages:list`
- **Method:** GET
- **Capability:** `sales.companies.read`
- **Description:** List pipeline stage definitions (companies_stage_options): id, name, order—subscriber-specific labels.
### `sales:companies_extra:set`
- **Method:** POST
- **Capability:** `sales.companies.update`
- **Description:** Set a subscriber custom field value (companies_extra): update by companies_extra_id, or upsert by system_subscriber_companies_extra_id (insert when no row and field definition is active). Same capability as company edit on view_company.
- **JSON body:**
- `companies_id`: int, required
- `custom_field_value`: string or boolean (checkboxes: use true/false or 1/0)
- `companies_extra_id`: int, use this XOR system_subscriber_companies_extra_id
- `system_subscriber_companies_extra_id`: int, use this XOR companies_extra_id
### `sales:contacts:list`
- **Method:** GET
- **Capability:** `sales.contacts.read`
- **Description:** List contacts for a company.
- **Query:**
- `companies_id`: int, required
### `sales:contacts:get`
- **Method:** GET
- **Capability:** `sales.contacts.read`
- **Description:** Get one contact.
- **Query:**
- `contacts_id`: int, required
### `sales:contacts:create`
- **Method:** POST
- **Capability:** `sales.contacts.create`
- **Description:** Create a contact on a company; when email is provided it is stored in contacts_contact as type Email.
- **JSON body:**
- `companies_id`: int, required
- `contacts_first_name`: string
- `contacts_last_name`: string
- `contacts_title`: optional string
- `email`: optional string (preferred; saved to contacts_contact Email)
- `contacts_email`: optional string alias for email
### `sales:contacts:update`
- **Method:** POST
- **Capability:** `sales.contacts.update`
- **Description:** Update contact fields (tenant-scoped), including optional email upsert in contacts_contact.
- **JSON body:**
- `contacts_id`: int, required
- `contacts_first_name`: optional string
- `contacts_last_name`: optional string
- `contacts_title`: optional string
- `contacts_status`: optional string
- `email`: optional string (preferred; empty clears Email contact method)
- `contacts_email`: optional string alias for email
### `sales:contacts:find`
- **Method:** GET
- **Capability:** `sales.contacts.read`
- **Description:** Find contacts by email (case-insensitive substring) across the tenant; returns companies_name and contacts_companies_id.
- **Query:**
- `email`: string, required
- `limit`: optional max 100
- `hints`: optional 0 to omit agent_hints
### `sales:hashtags:search`
- **Method:** GET
- **Capability:** `sales.records.read`
- **Description:** Search CRM records by note hashtag token (same hashtag behavior humans use in companies_list hashtag links). Accepts hashtag=tag or hashtag=#tag and returns grouped companies/contacts/quotes/notes.
- **Query:**
- `hashtag`: required string hashtag token, with or without leading #
- `entity`: optional all|companies|contacts|quotes|notes (default all)
- `limit`: optional int, default 50, max 200
- `offset`: optional int, default 0
- `hints`: optional 0 to omit agent_hints
### `sales:company_email_log:list`
- **Method:** GET
- **Capability:** `sales.notes.create`
- **Description:** List structured email-activity rows for a company. Returns HTTP 501 not_configured with a hint if table companies_email_exchange is missing—apply migrations/add_companies_email_exchange.sql first.
- **Query:**
- `companies_id`: int, required
- `limit`: optional
- `hints`: optional 0 to omit agent_hints
### `sales:company_email_log:create`
- **Method:** POST
- **Capability:** `sales.notes.create`
- **Description:** Create a structured email log entry on a company. Inbound rows (direction=in) can auto-classify reply sentiment, write note_type telemetry, and auto-update companies_temperature with dedupe by message_id + tenant and cooldown protection for recent manual overrides.
- **JSON body:**
- `companies_id`: int, required
- `direction`: in|out, required
- `summary`: string, required
- `subject`: optional string (max 500)
- `occurred_at`: optional datetime (default now)
- `message_id`: optional string
- `auto_track_inbound_reply`: optional bool; default true when direction=in
- `reply_classification`: optional positive|neutral|negative|inbound_positive|inbound_neutral|inbound_negative
- `auto_update_temperature`: optional bool; default true
- `manual_override_cooldown_hours`: optional int 0..168 (default from feature toggle, fallback 24)
- `force_temperature_update`: optional bool to bypass cooldown guard
### `sales:notes:create`
- **Method:** POST
- **Capability:** `sales.notes.create`
- **Description:** Add a note on a company or contact. Optional is_recurring creates recurring_tasks (same as view_company “Make this a task”). Optional note_type classifies activity (email_sent, follow_up_sent, inbound_positive, bounce, opt_out, etc.); inbound_positive sets company temperature Hot and inbound_negative sets Cold when companies_temperature exists (neutral/other types do not auto-change temperature).
- **JSON body:**
- `notes_table`: companies|contacts
- `companies_id`: int (required if notes_table=companies)
- `contacts_id`: int (required if notes_table=contacts)
- `user_note`: string
- `note_view`: internal|external, default internal
- `include_ai`: optional 0|1 (subscriber Gmail/email knowledge when 1)
- `note_type`: optional closed vocabulary; see help:guidelines sales note_type list
- `is_recurring`: optional truthy to add recurring_tasks
- `recurrence_type`: required when is_recurring: once|daily|weekly|monthly (omit or empty defaults to once)
- `first_occurrence`: optional datetime string (default now)
- `end_date`: optional
- `occurrence_limit`: optional int, default 1
### `sales:notes:get`
- **Method:** GET
- **Capability:** `sales.notes.read`
- **Description:** Get one company-scoped note by user_notes_id (tenant-safe).
- **Query:**
- `user_notes_id`: int, required
### `sales:notes:list`
- **Method:** GET
- **Capability:** `sales.notes.read`
- **Description:** List notes for the tenant; optional companies_id scopes to one company (same as sales:records:read&entity=notes).
- **Query:**
- `companies_id`: optional int
- `limit`: optional, default 500, max 500
### `sales:records:read`
- **Method:** GET
- **Capability:** `sales.records.read`
- **Description:** Sales agent: read CRM entities. entity=companies includes Host (companies_user_id), employee_count, originating_user_id, originating_date_added when columns exist, pipeline stage, current_pipeline_value, companies_temperature when present, companies_extra[] unless include_companies_extra=0. Optional originating_user_id and originating_date_from/to filters on entity=companies. entity=notes includes note_type when present. entity=contacts supports email= substring filter and returns email, companies_name when set.
- **Query:**
- `entity`: companies|contacts|notes|tasks
- `companies_id`: optional filter when entity=notes
- `originating_user_id`: optional when entity=companies
- `originating_date_from`: optional when entity=companies
- `originating_date_to`: optional when entity=companies
- `email`: optional when entity=contacts (case-insensitive search)
- `limit`: optional
- `include_companies_extra`: optional 0 when entity=companies to omit custom fields
- `hints`: optional 0 to omit agent_hints
### `sales:notifications:list`
- **Method:** GET
- **Capability:** `sales.notifications.read`
- **Description:** Open in-app notifications for the acting user plus due/overdue personal task counts (nav parity). Product review request notifications can include review_request context and one_tap submit payloads.
### `sales:notifications:dismiss`
- **Method:** POST
- **Capability:** `sales.notifications.write`
- **Description:** Mark a notification as read (open_closed=1) for the acting user.
- **JSON body:**
- `users_notifications_id`: int, required
### `sales:todos:list`
- **Method:** GET
- **Capability:** `sales.todos.read`
- **Description:** List personal to-dos (user_todo) for the acting user; same source as My To-Do List.
- **Query:**
- `status`: optional open|closed|all, default all
- `limit`: optional int, default 100, max 200
- `hints`: optional 0 to omit agent_hints
### `sales:todos:create`
- **Method:** POST
- **Capability:** `sales.todos.write`
- **Description:** Add a personal to-do (user_todo) for the acting user.
- **JSON body:**
- `todo_text`: string, required
- `due_date`: YYYY-MM-DD, required
### `sales:todos:complete`
- **Method:** POST
- **Capability:** `sales.todos.write`
- **Description:** Mark a personal to-do complete (must be owned by acting user).
- **JSON body:**
- `user_notes_id`: int, required
### `sales:product_updates:list`
- **Method:** GET
- **Capability:** `sales.product_updates.read`
- **Description:** Subscriber-visible What's New entries (published, not internal-only).
- **Query:**
- `limit`: optional int, default 20, max 100
- `since_date`: optional, filter update_date >= date
- `after_id`: optional int, filter quote_rocket_update_id > id
### `sales:product_reviews:create`
- **Method:** POST
- **Capability:** `sales.product_reviews.write`
- **Description:** Capture a product review from an external Sales AI principal (1-5 rating + review text). Stores acting user/subscriber context plus optional model/provider metadata.
- **JSON body:**
- `rating`: int 1..5, required
- `review_text`: string, required
- `headline`: optional string
- `would_recommend`: optional boolean
- `companies_id`: optional int
- `contacts_id`: optional int
- `source`: optional string
- `reviewer_name`: optional string
- `reviewer_email`: optional string
- `agent_provider`: optional string
- `agent_model`: optional string
- `agent_run_id`: optional string
- `agent_identity_label`: optional string
### `sales:product_reviews:list`
- **Method:** GET
- **Capability:** `sales.product_reviews.read`
- **Description:** List captured product reviews for the tenant (paginated).
- **Query:**
- `limit`: optional int, default 50, max 200
- `offset`: optional int, default 0
- `companies_id`: optional int
- `agent_type`: optional sales|service
- `hints`: optional 0 to omit agent_hints
### `sales:feature_feedback:create`
- **Method:** POST
- **Capability:** `sales.feature_feedback.write`
- **Description:** Capture enhancement feedback from external Sales AI principals when a feature does not meet their exact needs.
- **JSON body:**
- `title`: string, required
- `details`: string, required
- `feedback_type`: optional improvement|bug|request|ux|other (default improvement)
- `priority`: optional low|normal|high|critical (default normal)
- `feature_key`: optional string
- `companies_id`: optional int
- `contacts_id`: optional int
- `source`: optional string
- `agent_provider`: optional string
- `agent_model`: optional string
- `agent_run_id`: optional string
- `agent_identity_label`: optional string
### `sales:feature_feedback:list`
- **Method:** GET
- **Capability:** `sales.feature_feedback.read`
- **Description:** List feature feedback captured from external agents (paginated).
- **Query:**
- `limit`: optional int, default 50, max 200
- `offset`: optional int, default 0
- `feedback_type`: optional improvement|bug|request|ux|other
- `priority`: optional low|normal|high|critical
- `hints`: optional 0 to omit agent_hints
### `sales:goals:get`
- **Method:** GET
- **Capability:** `sales.goals.read`
- **Description:** Get goal settings for the acting user (or optional same-tenant for_user_id). Returns core and migrated goal columns when present.
- **Query:**
- `for_user_id`: optional int in same subscriber; defaults to acting_user_id
- `hints`: optional 0 to omit agent_hints
### `sales:goals:update`
- **Method:** POST
- **Capability:** `sales.goals.write`
- **Description:** Update one or more goal fields for the acting user (or optional same-tenant for_user_id). Supports base goals and optional migrated goal columns.
- **JSON body:**
- `for_user_id`: optional int in same subscriber; defaults to acting_user_id
- `goals`: object keyed by goal field names (recommended)
- `total_clients_goal`: optional int >= 0
- `monthly_clients_goal`: optional int >= 0
- `total_prospects_goal`: optional int >= 0
- `monthly_prospects_goal`: optional int >= 0
- `total_quotes_goal`: optional int >= 0 when column exists
- `monthly_quotes_goal`: optional int >= 0 when column exists
- `consistency_goal_pct`: optional number clamped 0..100 when column exists
- `client_retention_goal_pct`: optional number clamped 0..100 when column exists
- `avg_underwriting_time_goal`: optional int >= 0 when column exists
- `client_stability_goal_days`: optional int >= 0 when column exists
### `sales:coach:get`
- **Method:** GET
- **Capability:** `sales.coach.read`
- **Description:** Get Personal Coach settings for acting user or optional same-tenant for_user_id. Requires personal_coach entitlement.
- **Query:**
- `for_user_id`: optional int in same subscriber; defaults to acting_user_id
- `hints`: optional 0 to omit agent_hints
### `sales:coach:update`
- **Method:** POST
- **Capability:** `sales.coach.write`
- **Description:** Update Personal Coach enabled/frequency/day for acting user or optional same-tenant for_user_id. Requires personal_coach entitlement. External machine users are forced to enabled + bi_weekly + Monday defaults.
- **JSON body:**
- `for_user_id`: optional int in same subscriber; defaults to acting_user_id
- `enabled`: optional 0|1 (ignored for external_machine_agent; forced to 1)
- `report_frequency`: required weekly|bi_weekly|semi_monthly|monthly (forced bi_weekly for external_machine_agent)
- `report_day_of_week`: required int 0..6 (forced 1 Monday for external_machine_agent)
### `sales:quotes:list`
- **Method:** GET
- **Capability:** `sales.quotes.read`
- **Description:** List payroll proposals (quotes) for the tenant via company scope.
### `sales:quotes:get`
- **Method:** GET
- **Capability:** `sales.quotes.read`
- **Description:** Get one payroll proposal by id.
- **Query:**
- `payroll_proposal_id`: int, required
### `sales:enrollment_customers:list`
- **Method:** GET
- **Capability:** `sales.enrollment.read`
- **Description:** List customer portal accounts for one company.
- **Query:**
- `companies_id`: int, required
### `sales:enrollment_customers:create`
- **Method:** POST
- **Capability:** `sales.enrollment.write`
- **Description:** Invite/create a customer portal account.
- **JSON body:**
- `companies_id`: int, required
- `email`: string, required
- `full_name`: string, required
- `temp_password`: optional string
### `sales:enrollment_customers:update`
- **Method:** POST
- **Capability:** `sales.enrollment.admin`
- **Description:** Update customer portal account status (active|disabled).
- **JSON body:**
- `companies_id`: int, required
- `portal_customer_id`: int, required
- `status`: string, required
### `sales:enrollment_customers:reset_password`
- **Method:** POST
- **Capability:** `sales.enrollment.admin`
- **Description:** Reset customer portal password and return a temporary password.
- **JSON body:**
- `companies_id`: int, required
- `portal_customer_id`: int, required
- `temp_password`: optional string
### `sales:enrollment_documents:list`
- **Method:** GET
- **Capability:** `sales.enrollment.read`
- **Description:** List enrollment documents.
- **Query:**
- `companies_id`: int, required
- `limit`: optional int
### `sales:enrollment_documents:create`
- **Method:** POST
- **Capability:** `sales.enrollment.write`
- **Description:** Create enrollment document metadata record.
- **JSON body:**
- `companies_id`: int, required
- `document_name`: string, required
- `document_category`: optional string
- `document_status`: optional string
- `file_path`: string, required
- `file_size_bytes`: optional int
- `mime_type`: optional string
- `requires_signature`: optional bool
### `sales:enrollment_employees:list`
- **Method:** GET
- **Capability:** `sales.enrollment.read`
- **Description:** List employee roster records for enrollment.
- **Query:**
- `companies_id`: int, required
### `sales:enrollment_employees:upsert`
- **Method:** POST
- **Capability:** `sales.enrollment.write`
- **Description:** Create or update an enrollment employee row.
- **JSON body:**
- `companies_id`: int, required
- `portal_employee_id`: optional int for update
- `employee_first_name`: string, required
- `employee_last_name`: string, required
- `employee_email`: optional string
- `employee_title`: optional string
- `enrollment_status`: optional string
- `onboarding_step`: optional string
### `sales:enrollment_notes:list`
- **Method:** GET
- **Capability:** `sales.enrollment.read`
- **Description:** List enrollment notes.
- **Query:**
- `companies_id`: int, required
- `limit`: optional int
### `sales:enrollment_notes:create`
- **Method:** POST
- **Capability:** `sales.enrollment.write`
- **Description:** Create an enrollment note.
- **JSON body:**
- `companies_id`: int, required
- `note_body`: string, required
- `visibility`: optional shared|subscriber_only
### `sales:enrollment_tasks:list`
- **Method:** GET
- **Capability:** `sales.enrollment.read`
- **Description:** List enrollment tasks and approvals.
- **Query:**
- `companies_id`: int, required
### `sales:enrollment_tasks:create`
- **Method:** POST
- **Capability:** `sales.enrollment.write`
- **Description:** Create an enrollment task.
- **JSON body:**
- `companies_id`: int, required
- `task_title`: string, required
- `task_details`: optional string
- `task_status`: optional string
- `due_date`: optional YYYY-MM-DD
- `assigned_to_type`: optional customer|subscriber
- `assigned_to_user_id`: optional int
- `assigned_to_customer_id`: optional int
- `requires_approval`: optional bool
### `sales:enrollment_tasks:update`
- **Method:** POST
- **Capability:** `sales.enrollment.write`
- **Description:** Update enrollment task status.
- **JSON body:**
- `companies_id`: int, required
- `portal_task_id`: int, required
- `task_status`: string, required
### `sales:enrollment_signatures:list`
- **Method:** GET
- **Capability:** `sales.enrollment.read`
- **Description:** List enrollment signature requests and outcomes.
- **Query:**
- `companies_id`: int, required
### `sales:enrollment_signatures:create`
- **Method:** POST
- **Capability:** `sales.enrollment.write`
- **Description:** Request a new enrollment signature.
- **JSON body:**
- `companies_id`: int, required
- `portal_document_id`: int, required
- `signer_name`: string, required
- `signer_email`: string, required
### `sales:enrollment_signatures:sign`
- **Method:** POST
- **Capability:** `sales.enrollment.write`
- **Description:** Apply a signature to a requested enrollment signature.
- **JSON body:**
- `companies_id`: int, required
- `portal_signature_id`: int, required
- `signature_value`: string, required
### `sales:enrollment_notifications:list`
- **Method:** GET
- **Capability:** `sales.enrollment.read`
- **Description:** List enrollment notifications for a customer or company.
- **Query:**
- `companies_id`: int, required
- `portal_customer_id`: optional int
### `sales:enrollment_notifications:dismiss`
- **Method:** POST
- **Capability:** `sales.enrollment.write`
- **Description:** Mark one enrollment notification as read.
- **JSON body:**
- `companies_id`: int, required
- `portal_customer_id`: optional int
- `portal_notification_id`: int, required
### `sales:enrollment_timeline:list`
- **Method:** GET
- **Capability:** `sales.enrollment.read`
- **Description:** List enrollment timeline audit events.
- **Query:**
- `companies_id`: int, required
- `limit`: optional int