API Reference

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

Routes (24)

service:help:spec

GET service.help.read

Machine-readable API catalog for the Service agent.

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

service:help:openapi

GET service.help.read

OpenAPI 3 YAML fragment for the Service agent.

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

service:help:markdown

GET service.help.read

Markdown summary for the Service agent API.

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

service:help:guidelines

GET service.help.read

Best practices and workflows for external Service agents, including goals/coach usage and pipeline health/score semantics.

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

service:records:read

GET service.records.read

Read CRM entities for the tenant. entity=companies includes Host, employee_count, originating_user_id, originating_date_added when columns exist, pipeline stage, current_pipeline_value, companies_extra[] unless include_companies_extra=0. Optional originating_user_id and originating_date_from/to on entity=companies. entity=contacts supports email= (case-insensitive substring).

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|false|off|no omits agent_hints on this and other GET JSON responses

service:companies:update

POST service.companies.update

Update core company fields for the tenant (same fields as sales:companies:update), including employee_count. Requires view_company menu access for the acting user.

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

service:notes:list

GET service.records.read

Alias for service:records:read&entity=notes (resource=notes&action=list).

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

service:notes_tasks:create

POST service.notes_tasks.create

Create a note (and optional recurring task) on a company or contact.

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

JSON Body

  • companies_id: int
  • contacts_id: int
  • user_note: string
  • note_view: internal|external
  • notes_table: companies|contacts
  • is_recurring: optional bool
  • recurrence_type: optional string
  • first_occurrence: optional string
  • end_date: optional string
  • occurrence_limit: optional int
  • include_ai: optional 0|1 (subscriber Gmail/email knowledge when 1; default 0)

service:notes:get

GET service.notes.read

Get one note by user_notes_id (scoped via company tenant).

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

Query Parameters

  • user_notes_id: int, required

service:notifications:list

GET service.notifications.read

Open in-app notifications for the acting user plus due/overdue personal task counts. 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}

service:notifications:dismiss

POST service.notifications.write

Mark a notification as read 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

service:todos:list

GET service.todos.read

List personal to-dos for the acting user (My To-Do List parity).

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

service:todos:create

POST service.todos.write

Add a personal to-do 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

service:todos:complete

POST service.todos.write

Mark a personal to-do complete.

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

JSON Body

  • user_notes_id: int, required

service:product_updates:list

GET service.product_updates.read

Subscriber-visible What's New entries.

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
  • after_id: optional int

service:product_reviews:create

POST service.product_reviews.write

Capture a product review from an external Service AI principal (same payload model as Sales route).

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

service:product_reviews:list

GET service.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

service:feature_feedback:create

POST service.feature_feedback.write

Capture enhancement feedback from external Service AI principals when functionality is not meeting 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

service:feature_feedback:list

GET service.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

service:goals:get

GET service.goals.read

Get goal settings for the acting user (or optional same-tenant for_user_id).

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

service:goals:update

POST service.goals.write

Update one or more goal fields for the acting user (or optional same-tenant for_user_id).

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

service:coach:get

GET service.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

service:coach:update

POST service.coach.write

Update Personal Coach settings 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)

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:
  "/service/help/spec":
    get:
      operationId: service_help_spec
      summary: "Machine-readable API catalog for the Service agent."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/help/openapi":
    get:
      operationId: service_help_openapi
      summary: "OpenAPI 3 YAML fragment for the Service agent."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/help/markdown":
    get:
      operationId: service_help_markdown
      summary: "Markdown summary for the Service agent API."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/help/guidelines":
    get:
      operationId: service_help_guidelines
      summary: "Best practices and workflows for external Service agents, including goals\/coach usage and pipeline health\/score semantics."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/records/read":
    get:
      operationId: service_records_read
      summary: "Read CRM entities for the tenant. entity=companies includes Host, employee_count, originating_user_id, originating_date_added when columns exist, pipeline stage, current_pipeline_value, companies_extra[] unless include_companies_extra=0. Optional originating_user_id and originating_date_from\/to on entity=companies. entity=contacts supports email= (case-insensitive substring)."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/companies/update":
    post:
      operationId: service_companies_update
      summary: "Update core company fields for the tenant (same fields as sales:companies:update), including employee_count. Requires view_company menu access for the acting user."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/hashtags/search":
    get:
      operationId: service_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 for the tenant."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/notes/list":
    get:
      operationId: service_notes_list
      summary: "Alias for service:records:read&entity=notes (resource=notes&action=list)."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/notes_tasks/create":
    post:
      operationId: service_notes_tasks_create
      summary: "Create a note (and optional recurring task) on a company or contact."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - name: resource
          in: query
          required: true
          schema:
            type: string
            default: "notes_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
  "/service/notes/get":
    get:
      operationId: service_notes_get
      summary: "Get one note by user_notes_id (scoped via company tenant)."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/notifications/list":
    get:
      operationId: service_notifications_list
      summary: "Open in-app notifications for the acting user plus due\/overdue personal task counts. 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: [service]
        - 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
  "/service/notifications/dismiss":
    post:
      operationId: service_notifications_dismiss
      summary: "Mark a notification as read for the acting user."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/todos/list":
    get:
      operationId: service_todos_list
      summary: "List personal to-dos for the acting user (My To-Do List parity)."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/todos/create":
    post:
      operationId: service_todos_create
      summary: "Add a personal to-do for the acting user."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/todos/complete":
    post:
      operationId: service_todos_complete
      summary: "Mark a personal to-do complete."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/product_updates/list":
    get:
      operationId: service_product_updates_list
      summary: "Subscriber-visible What's New entries."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/product_reviews/create":
    post:
      operationId: service_product_reviews_create
      summary: "Capture a product review from an external Service AI principal (same payload model as Sales route)."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/product_reviews/list":
    get:
      operationId: service_product_reviews_list
      summary: "List captured product reviews for the tenant (paginated)."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/feature_feedback/create":
    post:
      operationId: service_feature_feedback_create
      summary: "Capture enhancement feedback from external Service AI principals when functionality is not meeting needs."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/feature_feedback/list":
    get:
      operationId: service_feature_feedback_list
      summary: "List feature feedback captured from external agents (paginated)."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/goals/get":
    get:
      operationId: service_goals_get
      summary: "Get goal settings for the acting user (or optional same-tenant for_user_id)."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/goals/update":
    post:
      operationId: service_goals_update
      summary: "Update one or more goal fields for the acting user (or optional same-tenant for_user_id)."
      parameters:
        - name: agent
          in: query
          required: true
          schema:
            type: string
            enum: [service]
        - 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
  "/service/coach/get":
    get:
      operationId: service_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: [service]
        - 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
  "/service/coach/update":
    post:
      operationId: service_coach_update
      summary: "Update Personal Coach settings 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: [service]
        - 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

Markdown export

View generated markdown summary
# Quote Rocket Agent API (service)

**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=service&resource=...&action=...`

## Best practices (external agents)

- Full document: `service: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

### `service:help:spec`
- **Method:** GET
- **Capability:** `service.help.read`
- **Description:** Machine-readable API catalog for the Service agent.

### `service:help:openapi`
- **Method:** GET
- **Capability:** `service.help.read`
- **Description:** OpenAPI 3 YAML fragment for the Service agent.

### `service:help:markdown`
- **Method:** GET
- **Capability:** `service.help.read`
- **Description:** Markdown summary for the Service agent API.

### `service:help:guidelines`
- **Method:** GET
- **Capability:** `service.help.read`
- **Description:** Best practices and workflows for external Service agents, including goals/coach usage and pipeline health/score semantics.

### `service:records:read`
- **Method:** GET
- **Capability:** `service.records.read`
- **Description:** Read CRM entities for the tenant. entity=companies includes Host, employee_count, originating_user_id, originating_date_added when columns exist, pipeline stage, current_pipeline_value, companies_extra[] unless include_companies_extra=0. Optional originating_user_id and originating_date_from/to on entity=companies. entity=contacts supports email= (case-insensitive substring).
- **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|false|off|no omits agent_hints on this and other GET JSON responses

### `service:companies:update`
- **Method:** POST
- **Capability:** `service.companies.update`
- **Description:** Update core company fields for the tenant (same fields as sales:companies:update), including employee_count. Requires view_company menu access for the acting user.
- **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

### `service:hashtags:search`
- **Method:** GET
- **Capability:** `service.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 for the tenant.
- **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|false|off|no omits agent_hints

### `service:notes:list`
- **Method:** GET
- **Capability:** `service.records.read`
- **Description:** Alias for service:records:read&entity=notes (resource=notes&action=list).
- **Query:**
  - `companies_id`: optional int
  - `limit`: optional

### `service:notes_tasks:create`
- **Method:** POST
- **Capability:** `service.notes_tasks.create`
- **Description:** Create a note (and optional recurring task) on a company or contact.
- **JSON body:**
  - `companies_id`: int
  - `contacts_id`: int
  - `user_note`: string
  - `note_view`: internal|external
  - `notes_table`: companies|contacts
  - `is_recurring`: optional bool
  - `recurrence_type`: optional string
  - `first_occurrence`: optional string
  - `end_date`: optional string
  - `occurrence_limit`: optional int
  - `include_ai`: optional 0|1 (subscriber Gmail/email knowledge when 1; default 0)

### `service:notes:get`
- **Method:** GET
- **Capability:** `service.notes.read`
- **Description:** Get one note by user_notes_id (scoped via company tenant).
- **Query:**
  - `user_notes_id`: int, required

### `service:notifications:list`
- **Method:** GET
- **Capability:** `service.notifications.read`
- **Description:** Open in-app notifications for the acting user plus due/overdue personal task counts. Product review request notifications can include review_request context and one_tap submit payloads.

### `service:notifications:dismiss`
- **Method:** POST
- **Capability:** `service.notifications.write`
- **Description:** Mark a notification as read for the acting user.
- **JSON body:**
  - `users_notifications_id`: int, required

### `service:todos:list`
- **Method:** GET
- **Capability:** `service.todos.read`
- **Description:** List personal to-dos for the acting user (My To-Do List parity).
- **Query:**
  - `status`: optional open|closed|all, default all
  - `limit`: optional int, default 100, max 200
  - `hints`: optional 0 to omit agent_hints

### `service:todos:create`
- **Method:** POST
- **Capability:** `service.todos.write`
- **Description:** Add a personal to-do for the acting user.
- **JSON body:**
  - `todo_text`: string, required
  - `due_date`: YYYY-MM-DD, required

### `service:todos:complete`
- **Method:** POST
- **Capability:** `service.todos.write`
- **Description:** Mark a personal to-do complete.
- **JSON body:**
  - `user_notes_id`: int, required

### `service:product_updates:list`
- **Method:** GET
- **Capability:** `service.product_updates.read`
- **Description:** Subscriber-visible What's New entries.
- **Query:**
  - `limit`: optional int, default 20, max 100
  - `since_date`: optional
  - `after_id`: optional int

### `service:product_reviews:create`
- **Method:** POST
- **Capability:** `service.product_reviews.write`
- **Description:** Capture a product review from an external Service AI principal (same payload model as Sales route).
- **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

### `service:product_reviews:list`
- **Method:** GET
- **Capability:** `service.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

### `service:feature_feedback:create`
- **Method:** POST
- **Capability:** `service.feature_feedback.write`
- **Description:** Capture enhancement feedback from external Service AI principals when functionality is not meeting 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

### `service:feature_feedback:list`
- **Method:** GET
- **Capability:** `service.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

### `service:goals:get`
- **Method:** GET
- **Capability:** `service.goals.read`
- **Description:** Get goal settings for the acting user (or optional same-tenant for_user_id).
- **Query:**
  - `for_user_id`: optional int in same subscriber; defaults to acting_user_id
  - `hints`: optional 0 to omit agent_hints

### `service:goals:update`
- **Method:** POST
- **Capability:** `service.goals.write`
- **Description:** Update one or more goal fields for the acting user (or optional same-tenant for_user_id).
- **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

### `service:coach:get`
- **Method:** GET
- **Capability:** `service.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

### `service:coach:update`
- **Method:** POST
- **Capability:** `service.coach.write`
- **Description:** Update Personal Coach settings 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)