API reference/Outreach/Dashboards

.md

Get a dashboard

One dashboard with what each block shows now (results), as the user sees it on its tab. A block whose filters no longer match (a signal or colleague that is gone) has an error: fix it with POST /dashboards.

GEThttps://mysdr.app/api/v1/dashboards/{key}

A dashboard the user asks your agent to build: it shows as its own tab on the Dashboard in mySDR (the tabs are only dashboards; mySDR builds the first one, Overview with the key mysdr_overview, from the first data) and refreshes by itself. You describe it; mySDR draws it from the live Leads and Companies tables and the activity log, with the same filters as GET /tables/leads, so a block counts the same rows as the table. No HTML or code: a dashboard is a list of blocks of five types. Changing or removing it is something the user asks your agent, not a button in mySDR. These routes are the tools save_dashboard, list_dashboards, get_dashboard and delete_dashboard of the assistant server.

Authentication#

Send Authorization: Bearer gtk_…. Create the key under API keys in the menu. Every gtk_ key can call these routes, also while the Signals API is closed. A missing, invalid or revoked key is 401.

Path parameters#

  • key string · required — The key of the dashboard (pipeline_q4).

Response#

  • object string · required — Always dashboard. One of: dashboard.
  • key string · required — Your own name for it: lowercase letters, digits and _.
  • name string · required — The label of its tab.
  • description string | null · required — The line under the name.
  • position integer | null · required — Where its tab goes among the dashboards (1 = first); null = last.
  • blocks object[] · required — The blocks as saved.
  • via string | null · required — The name of the key that last saved it ("Claude").
  • created_at string · required — When it was created.
  • updated_at string · required — When it last changed.
  • dashboard_url string · required — Its tab in mySDR.
  • computed_at string · required — When the blocks were computed.
  • results object[] · required — Per block, in order: index, type, title, source, and result or error. A metric gives value (null when a percentage has nothing to divide by), unit (count or percent), previous, part and whole; a chart kind bars with groups (key, label, value) and total, or kind series with interval, series and buckets (start, current, values); a table columns, rows (id, href, cells) and total; a note its text. capped = there is more than the dashboard reads at once (5,000 leads, or 5,000 lines of the log per source), so the number is at least this. error (type, message, param) says why a block shows nothing, e.g. a filter on a signal that is gone.

Credits#

Free. This call never uses credits.

Errors#

  • 400 invalid_request — A key that is not valid.
  • 404 not_found — The workspace has no dashboard with this key.
  • 401 authentication_error — The Authorization header is missing, or the key is unknown or revoked.
  • 403 permission_error — API access is not part of your plan, or your account is suspended.
  • 429 rate_limit_error — More than 60 requests per minute, or more than 3 at the same time, on one key. Wait for the Retry-After header.
  • 503 service_unavailable — The API is temporarily unavailable. Retry later.
  • 500 internal_error — Something went wrong on our side.

Example

GET/dashboards/{key}
curl "https://mysdr.app/api/v1/dashboards/pipeline_q4" \
  -H "Authorization: Bearer $MYSDR_API_KEY"
Response
{
  "object": "dashboard",
  "key": "pipeline_q4",
  "name": "Pipeline Q4",
  "description": "Where Q4 stands, every morning.",
  "position": 1,
  "blocks": [
    {
      "type": "metric",
      "title": "Meetings booked",
      "source": "leads",
      "filters": {
        "lifecycle": [
          "meeting"
        ]
      }
    },
    {
      "type": "metric",
      "title": "Reply rate, 30 days",
      "source": "activity",
      "filters": {
        "types": [
          "email_replied",
          "linkedin_replied"
        ]
      },
      "divide_by": {
        "types": [
          "email_sent",
          "linkedin_message_sent"
        ]
      },
      "compare": true
    },
    {
      "type": "chart",
      "title": "Leads per stage",
      "source": "leads",
      "filters": {
        "lifecycle": [
          "open"
        ]
      },
      "group_by": "stage"
    },
    {
      "type": "chart",
      "title": "Emails and replies per day",
      "source": "activity",
      "filters": {
        "types": [
          "email_sent",
          "email_replied"
        ],
        "period": "last_30_days"
      },
      "group_by": "day"
    },
    {
      "type": "table",
      "title": "Open deals in HubSpot",
      "source": "leads",
      "filters": {
        "field_filters": [
          {
            "key": "hubspot",
            "equals": "open_deal"
          }
        ]
      },
      "columns": [
        "name",
        "company",
        "lifecycle",
        "next_action",
        "field.hubspot"
      ],
      "sort": {
        "by": "next_action",
        "order": "asc"
      },
      "limit": 25
    }
  ],
  "via": "Claude",
  "created_at": "2026-10-27T08:00:00.000Z",
  "updated_at": "2026-10-27T08:00:00.000Z",
  "dashboard_url": "https://mysdr.app/en/gtm/views/pipeline_q4",
  "computed_at": "2026-10-27T08:00:01.000Z",
  "results": [
    {
      "index": 0,
      "type": "metric",
      "title": "Meetings booked",
      "source": "leads",
      "result": {
        "type": "metric",
        "value": 4,
        "unit": "count",
        "previous": null,
        "part": null,
        "whole": null,
        "period": null,
        "capped": false
      },
      "error": null
    },
    {
      "index": 1,
      "type": "metric",
      "title": "Reply rate, 30 days",
      "source": "activity",
      "result": {
        "type": "metric",
        "value": 12.5,
        "unit": "percent",
        "previous": 9.1,
        "part": 10,
        "whole": 80,
        "period": "last_30_days",
        "capped": false
      },
      "error": null
    }
  ]
}