API reference/Outreach/Dashboards
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.
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#
keystring· required — The key of the dashboard (pipeline_q4).
Response#
objectstring· required — Alwaysdashboard. One of:dashboard.keystring· required — Your own name for it: lowercase letters, digits and_.namestring· required — The label of its tab.descriptionstring | null· required — The line under the name.positioninteger | null· required — Where its tab goes among the dashboards (1 = first); null = last.blocksobject[]· required — The blocks as saved.viastring | null· required — The name of the key that last saved it ("Claude").created_atstring· required — When it was created.updated_atstring· required — When it last changed.dashboard_urlstring· required — Its tab in mySDR.computed_atstring· required — When the blocks were computed.resultsobject[]· required — Per block, in order:index,type,title,source, andresultorerror. A metric givesvalue(null when a percentage has nothing to divide by),unit(countorpercent),previous,partandwhole; a chartkindbarswithgroups(key,label,value) andtotal, orkindserieswithinterval,seriesandbuckets(start,current,values); a tablecolumns,rows(id,href,cells) andtotal; a note itstext.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
curl "https://mysdr.app/api/v1/dashboards/pipeline_q4" \
-H "Authorization: Bearer $MYSDR_API_KEY"{
"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
}
]
}