> ## Documentation Index
> Fetch the complete documentation index at: https://docs.neoagent.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Edit one widget's code

> An admin's hand edit of one widget's own code, what Edit in the page's View code saves: a function widget's whole `def widget_<id>(ctx):` (`function`, nothing else: shared helpers and `collect(ctx)` change through `PUT /dashboards/<id>`), a described widget's `query`, an html widget's `html`. Stored as a new definition under the checks a `PUT` makes (422 `validation_error` with `details.errors`, every problem); the widget then carries `hand_edited_at` and `hand_edited_by` until its code changes another way. A `query` or `html` edit keeps the stored rows (`refresh_started` null); a `function` edit refreshes the dashboard. 409 `dashboard_update_conflict` when `definition_id` is no longer the one in use or the widget is gone (`details.definition_id`: read it again); 403 unless an admin.



## OpenAPI

````yaml https://api.neoagent.io/public-api/openapi.json put /public-api/dashboards/{dashboard_id}/widgets/{widget_id}/code
openapi: 3.1.0
info:
  description: >-
    Neo's public contract for the dashboard ChatAgent, partner integrations, and
    MSP automation. Every response is wrapped in a `{data, meta}` envelope;
    errors use `{error: {code, message, details?}, meta: {request_id}}`.
    Authenticate with a `Bearer neo_sk_<env>_<secret>` API key (service account)
    or a Microsoft Entra ID JWT (dashboard user). Signed-URL endpoints (end-user
    feedback links) take a `signature` query parameter instead.
  title: Neo Public API
  version: 1.0.0
servers:
  - url: https://api.neoagent.io
security: []
tags:
  - description: Service metadata — health, OpenAPI.
    name: Meta
  - description: Agents and workflows — read, version history, delete, stats.
    name: Agents
  - description: Agent/workflow execution history, sub-resources, retry/cancel.
    name: Executions
  - description: >-
      Every tool call the tenant's agents made in the last 30 days, within the
      caller's workflow access.
    name: Audit Log
  - description: PSA webhook events and their workflow-match results.
    name: Callbacks
  - description: Technician-in-the-loop approval requests.
    name: TIL requests
  - description: RMM script executions triggered by agents.
    name: RMM scripts
  - description: Dispatch-agent field-update decisions.
    name: Dispatch
  - description: The authenticated tenant.
    name: Tenant
  - description: Agent-builder schema catalogs (raw JSON payloads).
    name: Schemas
  - description: Escalate to the Neo team (HubSpot ticket).
    name: Escalation
  - description: Tenant settings.
    name: Settings
  - description: Tenant API-key management (dashboard JWT only).
    name: API keys
  - description: End-user feedback links (signed-URL auth).
    name: Feedback
  - description: End-client companies (CRUD + bulk-update).
    name: End companies
  - description: Channels — bind a CONVERSATIONAL agent to a transport (Teams or Slack).
    name: Channels
  - description: PSA/RMM/M365 integration status and connection management.
    name: Integrations
  - description: Technician roster (controls TIL routing and paging).
    name: Technicians
  - description: Future runs queued for TRIGGERED agents.
    name: Scheduled work
  - description: Subscription state and customer-facing credit usage (no provider $).
    name: Billing
  - description: Inbox messages and announcements.
    name: Inbox & Comms
  - description: Tenant-authored agent skills (CRUD) and the built-in skill catalog.
    name: Skills
paths:
  /public-api/dashboards/{dashboard_id}/widgets/{widget_id}/code:
    put:
      tags:
        - Dashboards
      summary: Edit one widget's code
      description: >-
        An admin's hand edit of one widget's own code, what Edit in the page's
        View code saves: a function widget's whole `def widget_<id>(ctx):`
        (`function`, nothing else: shared helpers and `collect(ctx)` change
        through `PUT /dashboards/<id>`), a described widget's `query`, an html
        widget's `html`. Stored as a new definition under the checks a `PUT`
        makes (422 `validation_error` with `details.errors`, every problem); the
        widget then carries `hand_edited_at` and `hand_edited_by` until its code
        changes another way. A `query` or `html` edit keeps the stored rows
        (`refresh_started` null); a `function` edit refreshes the dashboard. 409
        `dashboard_update_conflict` when `definition_id` is no longer the one in
        use or the widget is gone (`details.definition_id`: read it again); 403
        unless an admin.
      operationId: public_api.dashboards_widget_code_put
      parameters:
        - in: path
          name: dashboard_id
          required: true
          schema:
            type: string
        - in: path
          name: widget_id
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WidgetCodeRequest'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                properties:
                  data:
                    $ref: '#/components/schemas/PublicDashboardCard'
                  meta:
                    $ref: '#/components/schemas/SuccessMeta'
                required:
                  - data
                  - meta
                type: object
          description: Success.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
          description: Bad request — malformed input.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
          description: Unauthenticated — missing or invalid credentials.
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
          description: Forbidden — authenticated but not allowed.
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
          description: Not found.
        '409':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
          description: Conflict — the resource is in a state that blocks this operation.
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
          description: Request validation failed.
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
          description: Rate limited — see Retry-After.
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
          description: Internal server error.
      security:
        - bearerAuth: []
components:
  schemas:
    WidgetCodeRequest:
      description: 'A hand edit of one widget''s code: the field of its kind, one or more.'
      properties:
        definition_id:
          description: >-
            The definition the edit was made on (`definition_id` of the
            dashboard as read): a 409 when it is no longer the one in use.
          format: uuid
          title: Definition Id
          type: string
        function:
          anyOf:
            - maxLength: 200000
              type: string
            - type: 'null'
          default: null
          description: >-
            A function widget: its whole `def widget_<id>(ctx):`, decorators
            included, nothing else. Shared helpers and `collect(ctx)` are
            changed through a full `PUT`.
          title: Function
        html:
          anyOf:
            - maxLength: 64000
              type: string
            - type: 'null'
          default: null
          description: 'An html widget: its new `html`, under the same rules as on a `PUT`.'
          title: Html
        query:
          anyOf:
            - $ref: '#/components/schemas/PublicWidgetQuery'
            - type: 'null'
          default: null
          description: >-
            A described widget: its new `query`, checked against the dataset's
            columns.
      required:
        - definition_id
      title: WidgetCodeRequest
      type: object
    PublicDashboardCard:
      description: >-
        What a write answers: enough for the chat to open the dashboard beside
        it.
      properties:
        dashboard_id:
          title: Dashboard Id
          type: string
        definition_id:
          title: Definition Id
          type: string
        name:
          title: Name
          type: string
        refresh_started:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Refresh Started
        widget_count:
          title: Widget Count
          type: integer
        widget_ids:
          items:
            type: string
          title: Widget Ids
          type: array
      required:
        - dashboard_id
        - name
        - definition_id
        - widget_ids
        - widget_count
        - refresh_started
      title: PublicDashboardCard
      type: object
    SuccessMeta:
      properties:
        pagination:
          $ref: '#/components/schemas/Pagination'
        request_id:
          format: uuid
          type: string
        timings_ms:
          additionalProperties:
            type: number
          type: object
        warnings:
          description: >-
            Non-fatal warnings about the created/updated resource (e.g. an
            unhealthy PSA callback).
          items:
            type: string
          type: array
      required:
        - request_id
        - timings_ms
      type: object
    ErrorEnvelope:
      properties:
        error:
          properties:
            code:
              description: Stable machine-readable error code.
              type: string
            details:
              additionalProperties: true
              type: object
            message:
              type: string
          required:
            - code
            - message
          type: object
        meta:
          properties:
            request_id:
              format: uuid
              type:
                - string
                - 'null'
          type: object
      required:
        - error
        - meta
      type: object
    PublicWidgetQuery:
      description: >-
        A description over the dataset instead of a `widget_<id>` function: the
        rows kept (filters

        ANDed), how they group (0–2 columns, as the preset takes), what is
        measured per group, the order

        and the cut. Computed by Neo, never by the module. With `history`,
        measured per snapshot date

        over the stored snapshots (no `group_by`: the date is the group), for a
        trend the vendor does

        not keep, such as open tickets each Monday. A `table`'s description is
        `columns` instead of

        `group_by` and `measure`: the rows the filters keep, those columns, in
        `sort` order (`by` a

        column), at most `limit` (2,000).
      properties:
        columns:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          default: null
          description: >-
            Component `table` only: 1 to 12 dataset column keys, in order. A
            ticket column draws as its PSA link.
          title: Columns
        filter:
          items:
            $ref: '#/components/schemas/PublicFilter'
          maxItems: 20
          title: Filter
          type: array
        group_by:
          items:
            $ref: '#/components/schemas/PublicGroupBy'
          maxItems: 2
          title: Group By
          type: array
        history:
          anyOf:
            - $ref: '#/components/schemas/PublicHistory'
            - type: 'null'
          default: null
          description: >-
            Read the measure per scheduled refresh from the stored snapshots,
            oldest first; the dashboard needs a `schedule`.
        limit:
          anyOf:
            - maximum: 2000
              minimum: 1
              type: integer
            - type: 'null'
          default: null
          title: Limit
        measure:
          description: At least one on a chart; none on a table.
          items:
            $ref: '#/components/schemas/PublicMeasure'
          maxItems: 20
          title: Measure
          type: array
        sort:
          anyOf:
            - $ref: '#/components/schemas/PublicSort'
            - type: 'null'
          default: null
      title: PublicWidgetQuery
      type: object
    Pagination:
      properties:
        has_more:
          type: boolean
        next_cursor:
          type:
            - string
            - 'null'
      required:
        - next_cursor
        - has_more
      type: object
    PublicFilter:
      properties:
        column:
          title: Column
          type: string
        op:
          enum:
            - eq
            - ne
            - in
            - not_in
            - gt
            - gte
            - lt
            - lte
            - contains
            - is_null
            - not_null
          title: Op
          type: string
        value:
          default: null
          description: >-
            A list for in/not_in; none for is_null/not_null; the column's type
            otherwise.
          title: Value
      required:
        - column
        - op
      title: PublicFilter
      type: object
    PublicGroupBy:
      properties:
        bucket:
          anyOf:
            - enum:
                - day
                - week
                - month
              type: string
            - type: 'null'
          default: null
          description: Required on a date column, refused on any other.
          title: Bucket
        column:
          title: Column
          type: string
      required:
        - column
      title: PublicGroupBy
      type: object
    PublicHistory:
      description: >-
        Measure over the dataset's stored snapshots instead of its current rows:
        one point per

        `bucket` of snapshot dates (the latest snapshot in each, UTC calendar),
        the last `last` of

        them. A scheduled refresh stores one snapshot; the dashboard needs a
        `schedule`.
      properties:
        bucket:
          default: day
          description: >-
            One point per day, ISO week (from Monday) or month of snapshot
            dates.
          enum:
            - day
            - week
            - month
          title: Bucket
          type: string
        last:
          description: How many points, 1 to 52, e.g. 12 for the last 12 weeks.
          title: Last
          type: integer
      required:
        - last
      title: PublicHistory
      type: object
    PublicMeasure:
      properties:
        column:
          anyOf:
            - type: string
            - type: 'null'
          default: null
          description: Required except for count; a number column for sum, avg and median.
          title: Column
        fn:
          enum:
            - count
            - distinct
            - sum
            - avg
            - median
            - min
            - max
          title: Fn
          type: string
        label:
          anyOf:
            - pattern: ^[A-Za-z_][A-Za-z0-9_]{0,39}$
              type: string
            - type: 'null'
          default: null
          description: The series key; `<fn>` or `<fn>_<column>` when left out.
          title: Label
        where:
          description: >-
            Filters on this measure alone, ANDed with the query's `filter`:
            three counts with three `where`s make one row of headline numbers.
            Name each such measure with `label`.
          items:
            $ref: '#/components/schemas/PublicFilter'
          maxItems: 20
          title: Where
          type: array
      required:
        - fn
      title: PublicMeasure
      type: object
    PublicSort:
      properties:
        by:
          description: >-
            `label` (the group) or a measure's key; on a table, a dataset
            column.
          title: By
          type: string
        dir:
          default: desc
          enum:
            - asc
            - desc
          title: Dir
          type: string
      required:
        - by
      title: PublicSort
      type: object
  securitySchemes:
    bearerAuth:
      description: >-
        `Authorization: Bearer <token>` where `<token>` is either a
        `neo_sk_<env>_<secret>` API key (service account) or a Microsoft Entra
        ID access token (dashboard user).
      scheme: bearer
      type: http

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.