{"slug": "dashboards-v2-api-schema-endpoints-patch-updates", "title": "Dashboards V2 API - Schema, Endpoints & PATCH Updates", "summary": "SigNoz released a redesigned Dashboards V2 API with a new JSON/Terraform schema, partial PATCH updates, key-value tags, personal pins, and enhanced panel styling. The update, rolling out July 27, is backward-compatible and requires no action for most users, but those with scripts or Terraform should migrate to the new API.", "body_md": "SigNoz is rolling out a redesigned **Dashboards** experience. Your existing dashboards, queries, variables, and panels continue to work exactly as they do now. This release keeps all of that intact and adds improvements that make dashboards easier to find, organize, and manage at scale.\n\n**Dashboards get easier to find and manage:** organize with key-value tags, personal pins, shared saved views, and quick cloning, plus a defined JSON/Terraform schema that enables direct editing, partial (token-efficient) updates, and reliable AI-driven changes.**Panels get more expressive:** new styling controls (fill mode, line interpolation, disconnect lines, show points) and PNG/SVG export for sharing in reports and incident write-ups.\n\nWhat you need to know\n\n- Dashboards will be migrated in the week of 27th July.\n- Nothing breaks on the platform. Your existing dashboards keep working, and this rolls out alongside them.\n- If you don't use Terraform or don't have any scripts directly working with the SigNoz Dashboards APIs, no action is required from you today.\n\nIf you have scripts that use the Dashboards API directly\n\nWe suggest you migrate those scripts to use the new V2 Dashboards APIs. You can follow the examples in this guide below.\n\nIf you have dashboards synced via Terraform\n\nThe Terraform Provider release corresponding to this SigNoz release will contain the required script to migrate your resources to the new schema. You can run that, then arrange your resources and define any variables on top of that. See the [Terraform provider guide](https://signoz.io/docs/dashboards/terraform-provider-signoz/) for details.\n\nDashboards V2 API Guide\n\nDashboards APIs now work on a properly enforced schema that follows the [Perses](https://perses.dev/) schema guidelines.\n\nA dashboard is divided into layouts, and each layout has panels arranged in it. Variables can be used to filter data across panels as before.\n\nDashboards also have tags as `key: value`\n\npairs, which help organize them into groups and provide an easy way to query by key or value.\n\nThe full schema can be seen in the payload of the [new Create Dashboard API](https://signoz.io/api-reference/v0.132.1#/operations/CreateDashboardV2).\n\nBird's eye view of the dashboards schema\n\n```\n{\n    \"tags\": [\n        {\n            \"key\": \"string\",\n            \"value\": \"string\"\n        }\n    ],\n    \"spec\": {\n        \"display\": {\n            \"name\": \"string\",\n            \"description\": \"string\"\n        },\n        \"layouts\": [],\n        \"panels\": {\n            \"panel-name\": { /* panel details */ }\n        },\n        \"variables\": []\n    }\n}\n```\n\nDashboard APIs\n\nThe List and CRUD (Create, Read, Update, Delete) APIs for dashboards all now get a V2 variant:\n\n```\nGET    /api/v2/dashboards          -- List Dashboards\nPOST   /api/v2/dashboards          -- Create a Dashboard\nGET    /api/v2/dashboards/{id}     -- Fetch Details for a Dashboard\nPUT    /api/v2/dashboards/{id}     -- Update a Dashboard\nDELETE /api/v2/dashboards/{id}     -- Delete a Dashboard\n```\n\nLocking and unlocking a dashboard get new endpoints:\n\n```\nPUT    /api/v2/dashboards/{id}/lock  -- Lock a Dashboard\nDELETE /api/v2/dashboards/{id}/lock  -- Unlock a Dashboard\n```\n\nUsers can now personally pin any dashboard, so there's a special List API to get dashboards that takes pins into account:\n\n```\nGET /api/v2/users/me/dashboards  -- List Dashboards for a User\n```\n\nThe biggest quality-of-life improvement is the new partial updates API, so that updating dashboards no longer involves building the whole dashboard JSON again:\n\n```\nPATCH /api/v2/dashboards/{id}  -- Patch a Dashboard\n```\n\nFull details of all the APIs are present in the [API Reference](https://signoz.io/api-reference/v0.132.1#/operations/ListDashboardsV2).\n\nNew listing APIs\n\nBoth List APIs (the user-agnostic one and the user-specific one) now support pagination. They also get a proper query field where dashboards can be searched by name, description, tags, and other properties using many different operations.\n\nFollowing are some examples. Only the path differs between the two APIs; the API query parameters can be passed the same way.\n\n```\n## Get 20 latest dashboards\ncurl --location '<YOUR-SIGNOZ-URL>/api/v2/dashboards?limit=20' \\\n--header 'SIGNOZ-API-KEY: <YOUR-API-KEY>'\n\n## Get the next 20 latest dashboards\ncurl --location '<YOUR-SIGNOZ-URL>/api/v2/dashboards?limit=20&offset=20' \\\n--header 'SIGNOZ-API-KEY: <YOUR-API-KEY>'\n\n## Get the first 20 dashboards sorted in alphabetical order\ncurl --location '<YOUR-SIGNOZ-URL>/api/v2/dashboards?sort=name&order=asc&limit=20' \\\n--header 'SIGNOZ-API-KEY: <YOUR-API-KEY>'\n```\n\nSome examples of the query DSL:\n\n```\n## Get dashboards that contain \"prod\" in their name\n## Unencoded query: name contains prod\ncurl --location '<YOUR-SIGNOZ-URL>/api/v2/dashboards?query=name%20contains%20prod&limit=20' \\\n--header 'SIGNOZ-API-KEY: <YOUR-API-KEY>'\n\n## Get dashboards that have the `env = prod` tag on them or have \"prod\" in their name\n## Unencoded query: name contains prod OR env = prod\ncurl --location '<YOUR-SIGNOZ-URL>/api/v2/dashboards?query=name%20contains%20prod%20OR%20env%20%3D%20prod&limit=20' \\\n--header 'SIGNOZ-API-KEY: <YOUR-API-KEY>'\n```\n\nPartial updates API\n\nThis API allows for pinpointed updates to a dashboard, which makes building requests much easier.\n\nFor example, updating the description of a dashboard is just this:\n\n```\ncurl --location --request PATCH '<YOUR-SIGNOZ-URL>/api/v2/dashboards/<ID>' \\\n--header 'SIGNOZ-API-KEY: <YOUR-API-KEY>' \\\n--data '[\n    {\n        \"op\": \"add\",\n        \"path\": \"/spec/display/description\",\n        \"value\": \"New Description\"\n    }\n]'\n```\n\nAdding a tag:\n\n```\ncurl --location --request PATCH '<YOUR-SIGNOZ-URL>/api/v2/dashboards/<ID>' \\\n--header 'SIGNOZ-API-KEY: <YOUR-API-KEY>' \\\n--data '[\n    {\n        \"op\": \"add\",\n        \"path\": \"/tags/-\",\n        \"value\": {\n            \"key\": \"env\",\n            \"value\": \"prod\"\n        }\n    }\n]'\n```\n\nChanging the value for a tag:\n\n```\ncurl --location --request PATCH '<YOUR-SIGNOZ-URL>/api/v2/dashboards/<ID>' \\\n--header 'SIGNOZ-API-KEY: <YOUR-API-KEY>' \\\n--data '[\n    {\n        \"op\": \"replace\",\n        \"path\": \"/tags/0/value\",\n        \"value\": \"production\"\n    }\n]'\n```\n\nAdding a new panel involves one request object to add the panel, and another to add it to the layout:\n\n```\ncurl --location --request PATCH '<YOUR-SIGNOZ-URL>/api/v2/dashboards/<ID>' \\\n--header 'SIGNOZ-API-KEY: <YOUR-API-KEY>' \\\n--data '[\n    {\n        \"op\": \"add\",\n        \"path\": \"/spec/panels/196021a6-3b94-454c-9c9d-2b4170708038\",\n        \"value\": {\n            \"kind\": \"Panel\",\n            \"spec\": {\n                \"display\": {\n                    \"name\": \"CPU Time\"\n                },\n                \"plugin\": {\n                    \"kind\": \"signoz/TimeSeriesPanel\",\n                    \"spec\": {\n                        \"visualization\": {\n                            \"timePreference\": \"global_time\"\n                        },\n                        \"legend\": {\n                            \"position\": \"bottom\"\n                        },\n                        \"chartAppearance\": {\n                            \"lineStyle\": \"solid\",\n                            \"lineInterpolation\": \"spline\",\n                            \"fillMode\": \"none\"\n                        },\n                        \"formatting\": {\n                            \"unit\": \"s\"\n                        }\n                    }\n                },\n                \"queries\": [\n                    {\n                        \"kind\": \"time_series\",\n                        \"spec\": {\n                            \"plugin\": {\n                                \"kind\": \"signoz/CompositeQuery\",\n                                \"spec\": {\n                                    \"queries\": [\n                                        {\n                                            \"type\": \"builder_query\",\n                                            \"spec\": {\n                                                \"name\": \"A\",\n                                                \"signal\": \"metrics\",\n                                                \"source\": \"\",\n                                                \"stepInterval\": null,\n                                                \"disabled\": false,\n                                                \"filter\": {\n                                                    \"expression\": \"\"\n                                                },\n                                                \"having\": {\n                                                    \"expression\": \"\"\n                                                },\n                                                \"aggregations\": [\n                                                    {\n                                                        \"metricName\": \"system.cpu.time\",\n                                                        \"timeAggregation\": \"rate\",\n                                                        \"spaceAggregation\": \"sum\"\n                                                    }\n                                                ]\n                                            }\n                                        }\n                                    ]\n                                }\n                            }\n                        }\n                    }\n                ]\n            }\n        }\n    },\n    {\n        \"op\": \"add\",\n        \"path\": \"/spec/layouts/0/spec/items/-\",\n        \"value\": {\n            \"x\": 0,\n            \"y\": 6,\n            \"width\": 6,\n            \"height\": 6,\n            \"content\": {\n                \"$ref\": \"#/spec/panels/196021a6-3b94-454c-9c9d-2b4170708038\"\n            }\n        }\n    }\n]'\n```\n\nUpdating the filter in a query inside a panel, for example the panel added above:\n\n```\ncurl --location --request PATCH '<YOUR-SIGNOZ-URL>/api/v2/dashboards/<ID>' \\\n--header 'SIGNOZ-API-KEY: <YOUR-API-KEY>' \\\n--data '[\n    {\n        \"op\": \"replace\",\n        \"path\": \"/spec/panels/196021a6-3b94-454c-9c9d-2b4170708038/spec/queries/0/spec/plugin/spec/queries/0/spec/filter/expression\",\n        \"value\": \"service.name = '\\''signoz'\\''\"\n    }\n]'\n```\n\nRemoving a panel involves one request object to remove the panel, and another to remove it from the layout it is in (check which layout, and within that layout which item the panel is in, then remove that whole item):\n\n```\ncurl --location --request PATCH '<YOUR-SIGNOZ-URL>/api/v2/dashboards/<ID>' \\\n--header 'SIGNOZ-API-KEY: <YOUR-API-KEY>' \\\n--data '[\n    {\n        \"op\": \"remove\",\n        \"path\": \"/spec/panels/196021a6-3b94-454c-9c9d-2b4170708038\"\n    },\n    {\n        \"op\": \"remove\",\n        \"path\": \"/spec/layouts/0/spec/items/3\"\n    }\n]'\n```\n\nAdding a variable is similar to adding a tag. Here's an example of adding a dynamic variable named `httproute`\n\nthat takes values from the `http.route`\n\nattribute:\n\n```\ncurl --location --request PATCH '<YOUR-SIGNOZ-URL>/api/v2/dashboards/<ID>' \\\n--header 'SIGNOZ-API-KEY: <YOUR-API-KEY>' \\\n--data '[\n    {\n        \"op\": \"add\",\n        \"path\": \"/spec/variables/-\",\n        \"value\": {\n            \"kind\": \"ListVariable\",\n            \"spec\": {\n                \"name\": \"httproute\",\n                \"display\": {\n                    \"name\": \"httproute\",\n                    \"description\": \"\"\n                },\n                \"allowMultiple\": false,\n                \"allowAllValue\": true,\n                \"sort\": \"none\",\n                \"plugin\": {\n                    \"kind\": \"signoz/DynamicVariable\",\n                    \"spec\": {\n                        \"name\": \"http.route\",\n                        \"signal\": \"\"\n                    }\n                }\n            }\n        }\n    }\n]'\n```\n\nRemoving a variable just requires knowing the index it is on in the variables array:\n\n```\ncurl --location --request PATCH '<YOUR-SIGNOZ-URL>/api/v2/dashboards/<ID>' \\\n--header 'SIGNOZ-API-KEY: <YOUR-API-KEY>' \\\n--data '[\n    {\n        \"op\": \"remove\",\n        \"path\": \"/spec/variables/2\"\n    }\n]'\n```\n\n", "url": "https://wpnews.pro/news/dashboards-v2-api-schema-endpoints-patch-updates", "canonical_source": "https://signoz.io/docs/dashboards/dashboards-v2-api", "published_at": "2026-07-10 00:00:00+00:00", "updated_at": "2026-07-10 06:37:43.388443+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["SigNoz", "Perses", "Terraform"], "alternates": {"html": "https://wpnews.pro/news/dashboards-v2-api-schema-endpoints-patch-updates", "markdown": "https://wpnews.pro/news/dashboards-v2-api-schema-endpoints-patch-updates.md", "text": "https://wpnews.pro/news/dashboards-v2-api-schema-endpoints-patch-updates.txt", "jsonld": "https://wpnews.pro/news/dashboards-v2-api-schema-endpoints-patch-updates.jsonld"}}