API Reference

Generated from live external Agent API catalog metadata for SALES. Last generated at 2026-06-05T21:17:33+00:00.

Routes (67)

sales:help:spec

GET sales.help.read

Machine-readable API catalog, auth, errors, Agent Ledger, rate limits, and idempotency for the Sales agent.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}

sales:help:openapi

GET sales.help.read

OpenAPI 3 YAML fragment for tools that consume OpenAPI.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}

sales:help:markdown

GET sales.help.read

Human-readable markdown summary of the Sales agent API (UTF-8 text/plain).

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}

sales:help:guidelines

GET sales.help.read

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).

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}

sales:help:prompt

GET sales.help.read

Canonical wrapper/system prompt snippet for external Sales agent orchestration (JSON by default; use format=text for text/plain).

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}

sales:users:list

GET sales.users.read

List users in the subscriber tenant (max 500).

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}

sales:users:create

POST sales.users.create

Create a subscriber user (seat limits apply).

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

JSON Body

  • preferred_user: string (username)
  • temp_password: string
  • full_name: string
  • email: string
  • menu_profile_id: int

sales:users:get

GET sales.users.read

Get one user by id (tenant-scoped).

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&user_id={id}

Query Parameters

  • user_id: int, required

sales:users:update

POST sales.users.update

Update blocked_user and/or menu_profile_id for a user in the tenant.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

JSON Body

  • user_id: int, required
  • blocked_user: optional 0|1
  • menu_profile_id: optional int

sales:companies:list

GET sales.companies.read

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.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&limit=100&offset=0&include_companies_extra=1&pipeline_stage_id=optional

Query Parameters

  • 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

GET sales.companies.read

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).

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}&include_pipeline_breakdown=0|1

Query Parameters

  • 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

POST sales.companies.create

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.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

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

POST sales.companies.update

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.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

JSON Body

  • companies_id: int, required
  • assign_to_user_id: int, required

sales:companies:update

POST sales.companies.update

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.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

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

GET sales.companies.read

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.

Pattern: 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=1

Query Parameters

  • 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

GET sales.companies.read

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.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&for_user_id=optional

Query Parameters

  • for_user_id: optional int in same subscriber; defaults to acting_user_id
  • hints: optional 0 to omit agent_hints

sales:followups:list

GET sales.notes.read

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.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&for_user_id=optional&limit=100

Query Parameters

  • for_user_id: optional int
  • limit: optional, default 100, max 200
  • hints: optional 0 to omit agent_hints

sales:followups:complete

POST sales.notes.create

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.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

JSON Body

  • user_notes_id: int, required

sales:pipeline_stages:list

GET sales.companies.read

List pipeline stage definitions (companies_stage_options): id, name, order—subscriber-specific labels.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}

sales:companies_extra:set

POST sales.companies.update

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.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

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

GET sales.contacts.read

List contacts for a company.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}&limit=200

Query Parameters

  • companies_id: int, required

sales:contacts:get

GET sales.contacts.read

Get one contact.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&contacts_id={id}

Query Parameters

  • contacts_id: int, required

sales:contacts:create

POST sales.contacts.create

Create a contact on a company; when email is provided it is stored in contacts_contact as type Email.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

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

POST sales.contacts.update

Update contact fields (tenant-scoped), including optional email upsert in contacts_contact.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

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

GET sales.contacts.read

Find contacts by email (case-insensitive substring) across the tenant; returns companies_name and contacts_companies_id.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&email={address}&limit=50

Query Parameters

  • email: string, required
  • limit: optional max 100
  • hints: optional 0 to omit agent_hints

sales:company_email_log:list

GET sales.notes.create

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.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}&limit=50

Query Parameters

  • companies_id: int, required
  • limit: optional
  • hints: optional 0 to omit agent_hints

sales:company_email_log:create

POST sales.notes.create

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.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

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

POST sales.notes.create

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).

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

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

GET sales.notes.read

Get one company-scoped note by user_notes_id (tenant-safe).

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&user_notes_id={id}

Query Parameters

  • user_notes_id: int, required

sales:notes:list

GET sales.notes.read

List notes for the tenant; optional companies_id scopes to one company (same as sales:records:read&entity=notes).

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={optional}&limit=500

Query Parameters

  • companies_id: optional int
  • limit: optional, default 500, max 500

sales:records:read

GET sales.records.read

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.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&entity=companies|contacts|notes|tasks&companies_id=optional&limit=500

Query Parameters

  • 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

GET sales.notifications.read

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.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}

sales:notifications:dismiss

POST sales.notifications.write

Mark a notification as read (open_closed=1) for the acting user.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

JSON Body

  • users_notifications_id: int, required

sales:todos:list

GET sales.todos.read

List personal to-dos (user_todo) for the acting user; same source as My To-Do List.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&status=all|open|closed&limit=100

Query Parameters

  • status: optional open|closed|all, default all
  • limit: optional int, default 100, max 200
  • hints: optional 0 to omit agent_hints

sales:todos:create

POST sales.todos.write

Add a personal to-do (user_todo) for the acting user.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

JSON Body

  • todo_text: string, required
  • due_date: YYYY-MM-DD, required

sales:todos:complete

POST sales.todos.write

Mark a personal to-do complete (must be owned by acting user).

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

JSON Body

  • user_notes_id: int, required

sales:product_updates:list

GET sales.product_updates.read

Subscriber-visible What's New entries (published, not internal-only).

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&limit=20&since_date=YYYY-MM-DD&after_id=0

Query Parameters

  • 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

POST sales.product_reviews.write

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.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

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

GET sales.product_reviews.read

List captured product reviews for the tenant (paginated).

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&limit=50&offset=0&companies_id=optional&agent_type=optional

Query Parameters

  • 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

POST sales.feature_feedback.write

Capture enhancement feedback from external Sales AI principals when a feature does not meet their exact needs.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

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

GET sales.feature_feedback.read

List feature feedback captured from external agents (paginated).

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&limit=50&offset=0&feedback_type=optional&priority=optional

Query Parameters

  • 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

GET sales.goals.read

Get goal settings for the acting user (or optional same-tenant for_user_id). Returns core and migrated goal columns when present.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&for_user_id=optional

Query Parameters

  • for_user_id: optional int in same subscriber; defaults to acting_user_id
  • hints: optional 0 to omit agent_hints

sales:goals:update

POST sales.goals.write

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.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

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

GET sales.coach.read

Get Personal Coach settings for acting user or optional same-tenant for_user_id. Requires personal_coach entitlement.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&for_user_id=optional

Query Parameters

  • for_user_id: optional int in same subscriber; defaults to acting_user_id
  • hints: optional 0 to omit agent_hints

sales:coach:update

POST sales.coach.write

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.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

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

GET sales.quotes.read

List payroll proposals (quotes) for the tenant via company scope.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&limit=50&offset=0

sales:quotes:get

GET sales.quotes.read

Get one payroll proposal by id.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&payroll_proposal_id={id}

Query Parameters

  • payroll_proposal_id: int, required

sales:enrollment_customers:list

GET sales.enrollment.read

List customer portal accounts for one company.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}

Query Parameters

  • companies_id: int, required

sales:enrollment_customers:create

POST sales.enrollment.write

Invite/create a customer portal account.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

JSON Body

  • companies_id: int, required
  • email: string, required
  • full_name: string, required
  • temp_password: optional string

sales:enrollment_customers:update

POST sales.enrollment.admin

Update customer portal account status (active|disabled).

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

JSON Body

  • companies_id: int, required
  • portal_customer_id: int, required
  • status: string, required

sales:enrollment_customers:reset_password

POST sales.enrollment.admin

Reset customer portal password and return a temporary password.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

JSON Body

  • companies_id: int, required
  • portal_customer_id: int, required
  • temp_password: optional string

sales:enrollment_documents:list

GET sales.enrollment.read

List enrollment documents.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}&limit=200

Query Parameters

  • companies_id: int, required
  • limit: optional int

sales:enrollment_documents:create

POST sales.enrollment.write

Create enrollment document metadata record.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

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

GET sales.enrollment.read

List employee roster records for enrollment.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}

Query Parameters

  • companies_id: int, required

sales:enrollment_employees:upsert

POST sales.enrollment.write

Create or update an enrollment employee row.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

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

GET sales.enrollment.read

List enrollment notes.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}&limit=200

Query Parameters

  • companies_id: int, required
  • limit: optional int

sales:enrollment_notes:create

POST sales.enrollment.write

Create an enrollment note.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

JSON Body

  • companies_id: int, required
  • note_body: string, required
  • visibility: optional shared|subscriber_only

sales:enrollment_tasks:list

GET sales.enrollment.read

List enrollment tasks and approvals.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}

Query Parameters

  • companies_id: int, required

sales:enrollment_tasks:create

POST sales.enrollment.write

Create an enrollment task.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

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

POST sales.enrollment.write

Update enrollment task status.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

JSON Body

  • companies_id: int, required
  • portal_task_id: int, required
  • task_status: string, required

sales:enrollment_signatures:list

GET sales.enrollment.read

List enrollment signature requests and outcomes.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}

Query Parameters

  • companies_id: int, required

sales:enrollment_signatures:create

POST sales.enrollment.write

Request a new enrollment signature.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

JSON Body

  • companies_id: int, required
  • portal_document_id: int, required
  • signer_name: string, required
  • signer_email: string, required

sales:enrollment_signatures:sign

POST sales.enrollment.write

Apply a signature to a requested enrollment signature.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

JSON Body

  • companies_id: int, required
  • portal_signature_id: int, required
  • signature_value: string, required

sales:enrollment_notifications:list

GET sales.enrollment.read

List enrollment notifications for a customer or company.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}&portal_customer_id=optional

Query Parameters

  • companies_id: int, required
  • portal_customer_id: optional int

sales:enrollment_notifications:dismiss

POST sales.enrollment.write

Mark one enrollment notification as read.

Pattern: POST /agent_api_router.php?agent={agent}&resource={resource}&action={action} (JSON body)

JSON Body

  • companies_id: int, required
  • portal_customer_id: optional int
  • portal_notification_id: int, required

sales:enrollment_timeline:list

GET sales.enrollment.read

List enrollment timeline audit events.

Pattern: GET /agent_api_router.php?agent={agent}&resource={resource}&action={action}&companies_id={id}&limit=300

Query Parameters

  • companies_id: int, required
  • limit: optional int

OpenAPI YAML

View generated OpenAPI fragment
openapi: 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

Markdown export

View generated markdown summary
# 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