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

# Save card as widget template

> View-mode route. Copies one card of a dashboard the caller can see into a new widget template of the caller's organization: the card's `viz`, `spec` and `defaultLayout` are copied, `name` and `description` come from the body, and the server sets `isCustom: true` and `category: custom`. The card and the dashboard are not changed. Only a custom query card can be saved. The stored `spec` keeps its Task type unchanged, so the Task type is not checked again. In edit mode the app sends the draft card's content to Create custom widget (POST /dynamic-dashboard-widget) instead, without saving the dashboard.



## OpenAPI

````yaml /openapi/public/openapi-analytics.json post /dynamic-dashboard/{id}/card/{cardId}/save-as-widget-template
openapi: 3.0.0
info:
  title: API - Analytics
  version: 3.0.0
  description: API Documentation - RESTful API for field operations management.
servers:
  - url: https://apiweb.mile.app/api/v3
security:
  - bearerAuth: []
tags:
  - name: Dashboard
    description: >-
      Dashboard lets a user compose their own dashboard from any number of
      cards, start from a template, duplicate a dashboard, share it with roles,
      and save it back as an organization template. Each card owns its own
      widget row (a chart type plus a query spec), cloned from the widget
      catalogue (built-in widgets plus the organization's custom widgets), so
      renaming or editing a card never touches the catalogue or another
      dashboard. Dashboards are owned by their creator: roles they are shared
      with can view, duplicate and save as template, but only the owner can edit
      or delete. Every write reuses the dashboard permission family (view, add,
      edit and delete dashboard).


      The numbers behind each card come from one generic aggregation endpoint
      instead of one endpoint per chart: the client sends a batch of up to 12
      declarative query specs, the server injects the caller's organization, hub
      and soft-delete scope from the session, runs each spec read-only, and
      returns a flat columns and rows table per item. The catalog endpoints
      describe the data sources, fields and limits a client may use.
  - name: Report
    description: >-
      A report is a saved table definition over tasks of one task type or
      records of one data type: which fields to show, which hubs to include, and
      the default filters.
  - name: Insight Report
    description: >-
      Insight reports are written summaries of your operations, generated from
      your task and data records: findings, a summary and suggested actions. You
      set the context once per task type, then generate reports on demand or on
      a schedule.
paths:
  /dynamic-dashboard/{id}/card/{cardId}/save-as-widget-template:
    post:
      tags:
        - Dashboard
      summary: Save card as widget template
      description: >-
        View-mode route. Copies one card of a dashboard the caller can see into
        a new widget template of the caller's organization: the card's `viz`,
        `spec` and `defaultLayout` are copied, `name` and `description` come
        from the body, and the server sets `isCustom: true` and `category:
        custom`. The card and the dashboard are not changed. Only a custom query
        card can be saved. The stored `spec` keeps its Task type unchanged, so
        the Task type is not checked again. In edit mode the app sends the draft
        card's content to Create custom widget (POST /dynamic-dashboard-widget)
        instead, without saving the dashboard.
      operationId: saveDynamicDashboardCardAsWidgetTemplate
      parameters:
        - name: id
          in: path
          required: true
          description: Source dashboard `_id`
          schema:
            type: string
        - name: cardId
          in: path
          required: true
          description: The card's `cardId` in the stored dashboard's `widgets[]`
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - name
              properties:
                name:
                  type: string
                  maxLength: 200
                description:
                  type: string
              example:
                name: Done tasks per hub
                description: Saved from the Jakarta Hub - Daily dashboard.
        description: Widget template name and description
        required: true
      responses:
        '201':
          description: >-
            Created - the new widget template (`isCustom: true`, `category:
            custom`)
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                    example: true
                  code:
                    type: integer
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      schemaVersion:
                        type: integer
                        example: 1
                      name:
                        type: string
                        maxLength: 200
                        description: Literal display name, never translated
                      description:
                        type: string
                      category:
                        type: string
                        enum:
                          - custom
                        description: Always `custom`; set by the server
                      viz:
                        type: string
                        description: >-
                          Visualization: kpi, bar, line, donut, table, heatmap,
                          text, banner
                      spec:
                        type: object
                        description: >-
                          Neutral analytics query spec executed by POST
                          /analytics/query. See Run analytics query for the full
                          grammar.
                        properties:
                          specVersion:
                            type: integer
                          dataSourceId:
                            type: string
                          timeField:
                            type: string
                          measures:
                            type: array
                            items:
                              type: object
                              additionalProperties: true
                          dimensions:
                            type: array
                            items:
                              type: object
                              additionalProperties: true
                          filters:
                            type: array
                            items:
                              type: object
                              additionalProperties: true
                      composite:
                        type: object
                        description: >-
                          Multi-query widget `{kind, queries: {key: spec}}`;
                          `null` for ordinary widgets
                        additionalProperties: true
                      content:
                        type: object
                        description: '`{body}` for text and banner widgets; `null` otherwise'
                        properties:
                          body:
                            type: string
                            maxLength: 2000
                      defaultLayout:
                        type: object
                        description: Card placement on the grid
                        properties:
                          w:
                            type: integer
                            minimum: 2
                            description: Width in grid columns, 2 to `grid.columns`
                          h:
                            type: integer
                            minimum: 3
                            maximum: 18
                            description: >-
                              Height in rows, 3-18; `null` = as tall as its
                              content
                          x:
                            type: integer
                            minimum: 0
                            maximum: 48
                            description: >-
                              Optional column offset (free placement accepted,
                              not required)
                          'y':
                            type: integer
                            minimum: 0
                            description: Optional row offset
                      isCustom:
                        type: boolean
                        description: Always `true`; set by the server
                      _id:
                        type: string
                      organizationId:
                        type: string
                        description: The caller's organization id
                      createdBy:
                        type: string
                      updatedBy:
                        type: string
                      createdTime:
                        type: string
                        format: date-time
                      updatedTime:
                        type: string
                        format: date-time
              examples:
                response:
                  value:
                    status: true
                    code: 201
                    message: Widget has been added successfully.
                    data:
                      _id: 66fcd2a1e4b0a7d3c1f20c02
                      organizationId: 6650c2a1f3b9e4001c7d2a10
                      schemaVersion: 1
                      name: Done tasks per hub
                      description: Saved from the Jakarta Hub - Daily dashboard.
                      category: custom
                      viz: bar
                      spec:
                        specVersion: 1
                        dataSourceId: task
                        timeField: doneTime
                        measures:
                          - id: m1
                            fn: count
                        dimensions:
                          - id: d1
                            kind: terms
                            field: hubName
                            limit: 10
                        filters:
                          - id: f1
                            field: status
                            operator: eq
                            value: DONE
                      composite: null
                      content: null
                      defaultLayout:
                        w: 6
                        h: 6
                      isCustom: true
                      createdBy: planner@example.com
                      updatedBy: planner@example.com
                      createdTime: '2026-10-13T03:00:00.000000Z'
                      updatedTime: '2026-10-13T03:00:00.000000Z'
        '400':
          description: >-
            Bad Request - `dydsh-001` `name` missing or blank, `dydsh-009`
            `name` longer than 200 or `description` longer than 500, `dydsh-016`
            `name` or `description` is not a string, `dydsh-014` the card is not
            a custom query widget (built-in, text, banner or composite), or its
            stored `spec` is no longer valid
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                    example: false
                  message:
                    type: string
                    description: Human-readable reason
                  failedCode:
                    type: string
                    description: Structured error code, see Status Codes
              examples:
                response:
                  value:
                    status: false
                    message: >-
                      Only a custom query widget can be saved as a widget
                      template; this widget is text.
                    failedCode: dydsh-014
        '401':
          description: Unauthorized - missing, invalid or expired access token
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                    example: false
                  message:
                    type: string
                    description: Human-readable reason
                  failedCode:
                    type: string
                    description: Structured error code, see Status Codes
              examples:
                response:
                  value:
                    status: false
                    message: Unauthenticated.
                    failedCode: auth-034
        '403':
          description: Forbidden - the caller's role lacks `add/dashboard`
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                    example: false
                  message:
                    type: string
                    description: Human-readable reason
                  failedCode:
                    type: string
                    description: Structured error code, see Status Codes
              examples:
                response:
                  value:
                    status: false
                    message: >-
                      Access denied. You do not have permission for add
                      dashboard. Please contact your admin to request access.
                    failedCode: sys-035
        '404':
          description: >-
            Not Found - `dydsh-033` the dashboard does not exist, belongs to
            another organization, or is not visible to the caller
            (indistinguishable on purpose); `dydsh-042` the `cardId` is not on
            the stored dashboard ("This card no longer exists on the
            dashboard.")
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                    example: false
                  message:
                    type: string
                    description: Human-readable reason
                  failedCode:
                    type: string
                    description: Structured error code, see Status Codes
                  code:
                    type: integer
                    description: >-
                      HTTP status repeated in the body (repository failures
                      only)
                  data:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
                    description: Empty on most failures
              examples:
                response:
                  value:
                    status: false
                    code: 404
                    message: This card no longer exists on the dashboard.
                    data: []
                    failedCode: dydsh-042
        '422':
          description: >-
            Unprocessable - the document was written by a newer schema version
            than this API node understands (transient during a rolling deploy).
            Nothing was written.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                    example: false
                  message:
                    type: string
                    description: Human-readable reason
                  failedCode:
                    type: string
                    description: Structured error code, see Status Codes
                  code:
                    type: integer
                    description: >-
                      HTTP status repeated in the body (repository failures
                      only)
                  data:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
                    description: Empty on most failures
              examples:
                response:
                  value:
                    status: false
                    code: 422
                    message: >-
                      This dashboard was saved by a newer version of MileApp and
                      cannot be opened here. Please refresh the page and try
                      again.
                    data: []
                    failedCode: dydsh-040
        '500':
          description: Server Error - unexpected exception, logged server-side
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                    example: false
                  message:
                    type: string
                    description: Human-readable reason
                  failedCode:
                    type: string
                    description: Structured error code, see Status Codes
                  code:
                    type: integer
                    description: >-
                      HTTP status repeated in the body (repository failures
                      only)
                  data:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
                    description: Empty on most failures
              examples:
                response:
                  value:
                    status: false
                    code: 500
                    message: something_wrong
                    failedCode: dydsh-045
      security:
        - bearerAuth: []
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Use a valid Bearer token to authenticate.

````

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