Reports and analytics
Report datasets, ad-hoc and saved reports, dashboards, schedules, attribution, goals and forecast, plus sales, email and funnel analytics.
36 endpoints· 16 called live· 20 not exercised here· verified against http://127.0.0.1:8741
36 endpoints
GET/api/v1/salesshift/analytics/activity/healthNot exercised hereIs the projection actually keeping up, and what is it missing?
Is the projection actually keeping up, and what is it missing? Three independent views, because they fail independently: what this process published (producer counters), what the broker says the group has committed (lag), and what actually landed in Postgres. Any of them can be the broken one, and a single aggregated 'healthy' flag would hide which.
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/analytics/activity/health' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"success": "…"
}GET/api/v1/salesshift/analytics/activity/timelineNot exercised hereOrdered event history for a contact, a workflow, a run, or the whole org.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| contact_id | string(uuid)? | optional | |
| workflow_id | string(uuid)? | optional | |
| run_id | string(uuid)? | optional | |
| source | string? | optional | Matches ^(email|workflow)$. |
| days | integer | optional | Default 90. min 1. max 730. |
| limit | integer | optional | Default 200. min 1. max 1000. |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/analytics/activity/timeline' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"stream": "…",
"success": "…"
}GET/api/v1/salesshift/analytics/attributionCalled liveCredit won-deal revenue across the touches that preceded it.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| model | string | optional | Default "linear". |
| days | integer | optional | Default 180. max 1095. |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/analytics/attribution' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": {
"model": "str",
"deals_considered": "int",
"deals_attributed": "int",
"channels": [
"<empty list>"
]
}
}Errors
| Status | detail |
|---|---|
| 400 | model must be one of {...} |
POST/api/v1/salesshift/analytics/attribution/backfillNot exercised hereBackfill attribution touches for the organization.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/analytics/attribution/backfill' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "…",
"touches_created": "…"
}GET/api/v1/salesshift/analytics/campaign-performanceNot exercised herePer-campaign engagement: opened/replied come from ss_email_tracking.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| days | integer | optional | Default 30. |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/analytics/campaign-performance' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"success": "…"
}GET/api/v1/salesshift/analytics/contract-cycleNot exercised hereE-sign cycle: status counts, avg hours sent→completed, last 5 contracts.
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/analytics/contract-cycle' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"success": "…"
}GET/api/v1/salesshift/analytics/emailCalled liveSent/opened/clicked/replied/bounced counts from the email tracking table.
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/analytics/email' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": {
"totals": {
"sent": "int",
"opened": "int",
"clicked": "int",
"replied": "int",
"bounced": "int",
"failed": "int",
"unsubscribed": "int"
},
"rates": {
"open_rate": "float",
"click_rate": "float",
"reply_rate": "float",
"bounce_rate": "float"
},
"per_sequence": [
{
"sequence": "...",
"sent": "...",
"opened": "...",
"replied": "..."
},
"...x4"
]
}
}GET/api/v1/salesshift/analytics/engagementNot exercised hereReply-category breakdown + top 10 engaged contacts (opens + 5x replies).
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| days | integer | optional | Default 30. min 1. max 365. |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/analytics/engagement' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"success": "…"
}GET/api/v1/salesshift/analytics/funnelNot exercised hereDeal pipeline funnel: stages in display_order with OPEN deal count, value and each stage's share of the first stage (deals sit in their CURRENT stage).
Deal pipeline funnel: stages in display_order with OPEN deal count, value and each stage's share of the first stage (deals sit in their CURRENT stage). The status filter matches the Overview aggregate above — without it the same stage reported a different count on /analytics than on /overview, because won and lost deals kept their stage_id.
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/analytics/funnel' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"success": "…"
}GET/api/v1/salesshift/analytics/overviewCalled liveONE aggregate powering the Overview dashboard — every number is real SQL.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| days | integer | optional | Default 30. min 1. max 365. |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/analytics/overview' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": {
"days": "int",
"contacts": {
"total": "int",
"new_30d": "int"
},
"companies": {
"total": "int"
},
"deals": {
"open_count": "int",
"open_value": "float",
"won_value_30d": "float",
"stages": [
"...",
"...x6"
]
},
"emails": {
"sent_30d": "int",
"opened_30d": "int",
"replied_30d": "int",
"open_rate": "float",
"reply_rate": "float"
},
"sequences": {
"active": "int",
"enrolled": "int"
},
"campaigns": {
"total": "int",
"sending": "int",
"done": "int",
"last": {
"id": "...",
"name": "...",
"status": "...",
"sent": "...",
"opened": "..."
}
},
"meetings": {
"upcoming_7d": "int"
},
"contracts": {
"draft": "int",
"sent": "int",
"partially_signed": "int",
"completed": "int",
"voided": "int"
},
"opportunities": {
"open": "int",
"applications": "int"
},
"mailboxes": {
"count": "int"
},
"unread_notifications": "int",
"recent_activity": [
{
"title": "...",
"message": "...",
"created_at": "...",
"data": "..."
},
"...x10"
]
}
}GET/api/v1/salesshift/analytics/pipeline-historyCalled liveWhat the funnel looked like over time — the question fixed dashboards could never answer.
What the funnel looked like over time — the question fixed dashboards could never answer.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| days | integer | optional | Default 90. max 730. |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/analytics/pipeline-history' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": [
{
"date": "str",
"stage": "str",
"deal_count": "int",
"amount_cents": "int",
"weighted_cents": "int"
},
"...x9"
]
}POST/api/v1/salesshift/analytics/pipeline-snapshot/runNot exercised hereTake a pipeline snapshot immediately instead of waiting for the scheduled run.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/analytics/pipeline-snapshot/run' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"rows_written": "…",
"success": "…"
}GET/api/v1/salesshift/analytics/salesCalled liveWin/loss counts and pipeline value aggregated from the org's deals.
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/analytics/sales' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": {
"win_rate": "float",
"deals": {
"open": "int",
"won": "int",
"lost": "int"
},
"won_value": "float",
"avg_deal_size": "float",
"per_stage": [
{
"stage": "...",
"color": "...",
"count": "...",
"value": "..."
},
"...x6"
],
"velocity": [
{
"stage": "...",
"avg_hours": "...",
"transitions": "..."
},
"...x1"
],
"contacts_monthly": [
{
"month": "...",
"count": "..."
},
"...x1"
]
}
}GET/api/v1/salesshift/analytics/timeseriesNot exercised herePer-day sent/opened/replied counts.
Per-day sent/opened/replied counts. LEFT JOIN against generate_series so zero-days appear. Raw SQL: to_char lives in the projection only, so the asyncpg bind-param-in-GROUP-BY gotcha does not apply.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| days | integer | optional | Default 30. min 1. max 365. |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/analytics/timeseries' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"success": "…"
}GET/api/v1/salesshift/dashboardsCalled liveThe organization's dashboards.
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/dashboards' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": [
{
"id": "str",
"name": "str",
"description": "null",
"is_default": "bool",
"visibility": "str"
},
"...x1"
]
}POST/api/v1/salesshift/dashboardsNot exercised hereCreate a dashboard owned by the calling user.
Request body (required) — DashboardIn
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | required | |
| description | string? | optional | |
| is_default | boolean | optional | Default false. |
Values in the request below are typed placeholders, not sample data.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/dashboards' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "name": "<string>", "description": "<string>", "is_default": false }'Response · 201
{
"data": "…",
"success": "…"
}GET/api/v1/salesshift/dashboards/{dashboard_id}Not exercised hereOne dashboard with its widgets.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| dashboard_id | string(uuid) | required |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/dashboards/{dashboard_id}' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 404 | Dashboard not found |
POST/api/v1/salesshift/dashboards/{dashboard_id}/widgetsNot exercised hereAdd a widget backed by a saved report to a dashboard.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| dashboard_id | string(uuid) | required |
Request body (required) — WidgetIn
| Field | Type | Required | Notes |
|---|---|---|---|
| report_id | string(uuid) | required | |
| title_override | string? | optional | |
| x | integer | optional | Default 0. |
| y | integer | optional | Default 0. |
| w | integer | optional | Default 6. |
| h | integer | optional | Default 4. |
Values in the request below are typed placeholders, not sample data.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/dashboards/{dashboard_id}/widgets' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "report_id": "<string(uuid)>", "title_override": "<string>", "x": 0, "y": 0, "w": 6, "h": 4 }'Response · 201
{
"data": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 400 | Report not found in this workspace |
DELETE/api/v1/salesshift/dashboards/widgets/{widget_id}Not exercised hereRemove a widget from a dashboard.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| widget_id | string(uuid) | required |
Request
curl -X DELETE 'https://api.vxcloud.io/api/v1/salesshift/dashboards/widgets/{widget_id}' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"deleted": "…",
"success": "…"
}PATCH/api/v1/salesshift/deals/{deal_id}/forecast-categoryNot exercised hereSet a deal's forecast category (commit, best case, pipeline, omitted).
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| deal_id | string(uuid) | required |
Request body (required)
Untyped Dict[str, Any] body — there is no Pydantic model, so these are the field names the handler actually reads.
forecast_category
Values in the request below are typed placeholders, not sample data.
Request
curl -X PATCH 'https://api.vxcloud.io/api/v1/salesshift/deals/{deal_id}/forecast-category' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "forecast_category": "<value>" }'Response · 200
{
"forecast_category": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 400 | forecast_category must be one of {...} |
| 404 | Deal not found |
GET/api/v1/salesshift/emailsCalled liveInbox feed — every tracked outbound email with its engagement state.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| status | string? | optional | |
| limit | integer | optional | Default 50. min 1. max 200. |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/emails' \
-H "Authorization: Bearer $SS_TOKEN"import vxsdk
client = vxsdk.Client(access_token="$SS_TOKEN", vxcloud_url="https://api.vxcloud.io")
ss = client.salesshift
ss.list_emails(status="sent")import { VxCloud } from '@vxcloud/sdk';
const vx = new VxCloud({
accessToken: process.env.SS_TOKEN!,
vxcloudURL: 'https://api.vxcloud.io',
});
await vx.salesshift.listEmails('sent');import vxsdk "github.com/prodxcloud/vxcloud"
c, err := vxsdk.New(ctx,
vxsdk.WithJWT(os.Getenv("SS_TOKEN"), ""),
vxsdk.WithVxCloudURL("https://api.vxcloud.io"),
)
ss := c.SalesShift()
emails, err := ss.ListEmails(ctx, "sent")Response · 200
{
"success": "bool",
"data": [
{
"id": "str",
"to_email": "str",
"from_email": "str",
"contact_id": "str",
"contact_name": "str",
"subject": "str",
"status": "str",
"provider": "str",
"open_count": "int",
"click_count": "int",
"error": "str",
"body_html": "str",
"reply_body": "null",
"reply_category": "null",
"sent_at": "null",
"first_opened_at": "null",
"replied_at": "null",
"created_at": "str"
},
"...x2"
]
}GET/api/v1/salesshift/forecastCalled liveCategory roll-up from live deals, plus every submission for the period so called-vs-actual is visible rather than lost.
Category roll-up from live deals, plus every submission for the period so called-vs-actual is visible rather than lost.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| period_start | string? | optional | |
| period_end | string? | optional |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/forecast' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": {
"period_start": "str",
"period_end": "str",
"categories": {
"best_case": {
"deal_count": "...",
"amount_cents": "..."
},
"commit": {
"deal_count": "...",
"amount_cents": "..."
},
"pipeline": {
"deal_count": "...",
"amount_cents": "..."
}
},
"closed_won_cents": "int",
"submissions": [
{
"id": "...",
"user_id": "...",
"commit_cents": "...",
"best_case_cents": "...",
"pipeline_cents": "...",
"note": "...",
"submitted_at": "..."
},
"...x1"
]
}
}POST/api/v1/salesshift/forecast/submitNot exercised hereAppend a submission.
Append a submission. Never an upsert — comparing what a rep called in week 2 against what actually closed is the whole point.
Request body (required)
Untyped Dict[str, Any] body — there is no Pydantic model, so these are the field names the handler actually reads.
best_case_centscommit_centscurrencynoteperiod_endperiod_startpipeline_cents
Values in the request below are typed placeholders, not sample data.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/forecast/submit' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "best_case_cents": "<value>", "commit_cents": "<value>", "currency": "<value>", "note": "<value>", "period_end": "<value>", "period_start": "<value>", "pipeline_cents": "<value>" }'Response · 201
{
"data": "…",
"success": "…"
}GET/api/v1/salesshift/goalsCalled liveThe organization's goals.
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/goals' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": [
{
"id": "str",
"subject_type": "str",
"subject_id": "str",
"metric": "str",
"period": "str",
"period_start": "str",
"period_end": "str",
"target_value": "int",
"currency": "null"
},
"...x1"
]
}POST/api/v1/salesshift/goalsNot exercised hereCreate a goal against a known metric.
Request body (required)
Untyped Dict[str, Any] body — there is no Pydantic model, so these are the field names the handler actually reads.
currencymetricperiodperiod_endperiod_startsubject_idsubject_typetarget_value
Values in the request below are typed placeholders, not sample data.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/goals' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "currency": "<value>", "metric": "<value>", "period": "<value>", "period_end": "<value>", "period_start": "<value>", "subject_id": "<value>", "subject_type": "<value>", "target_value": "<value>" }'Response · 201
{
"data": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 400 | metric must be one of {...} |
GET/api/v1/salesshift/goals/leaderboardNot exercised hereAttainment per owner: actuals from the same data the reports use, goals from ss_goals, sorted by percentage of target.
Attainment per owner: actuals from the same data the reports use, goals from ss_goals, sorted by percentage of target.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| period_start | string? | optional | |
| period_end | string? | optional | |
| metric | string | optional | Default "revenue_won". |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/goals/leaderboard' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"success": "…"
}GET/api/v1/salesshift/reportsCalled liveThe organization's saved reports.
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/reports' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": [
{
"id": "str",
"name": "str",
"description": "null",
"dataset": "str",
"config": {
"measures": "...",
"dimensions": "..."
},
"owner_id": "int",
"visibility": "str",
"created_at": "str",
"updated_at": "str"
},
"...x1"
]
}POST/api/v1/salesshift/reportsCalled liveSave a report; the definition is compiled and run first, so an unrunnable report is never stored.
Request body (required) — ReportIn
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | required | |
| description | string? | optional | |
| dataset | string | required | |
| config | object | optional | |
| visibility | string | optional | Default "org". |
The body in the request below is the exact one sent during verification.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/reports' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "name": "Contacts by lifecycle stage", "dataset": "contacts", "config": { "dimensions": [ { "field": "contact.lifecycle_stage" } ], "measures": [ { "field": "contact.id", "agg": "count" } ] } }'Response · 201
{
"success": "bool",
"data": {
"id": "str",
"name": "str",
"dataset": "str",
"config": {
"dimensions": "...",
"measures": "..."
}
}
}Errors
| Status | detail |
|---|---|
| 400 | computed at runtime: str(exc) |
| 400 | Add at least one measure |
| 400 | Each dimension must be an object |
| 400 | Unknown dataset '<key>'. Available: campaigns, contacts, deals, email_activity, invoices, mrr_movements, payments, quotes, subscriptions, tasks |
GET/api/v1/salesshift/reports/{report_id}Called liveOne saved report, executed by default.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| report_id | string(uuid) | required |
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| run | boolean | optional | Default true. |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/reports/{report_id}' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": {
"id": "str",
"name": "str",
"description": "null",
"dataset": "str",
"config": {
"measures": [
"...",
"...x1"
],
"dimensions": [
"...",
"...x1"
]
},
"owner_id": "int",
"visibility": "str",
"created_at": "str",
"updated_at": "str",
"result": {
"dataset": "str",
"columns": [
"...",
"...x2"
],
"rows": [
"...",
"...x6"
],
"row_count": "int",
"truncated": "bool"
}
}
}Errors
| Status | detail |
|---|---|
| 404 | Report not found |
PATCH/api/v1/salesshift/reports/{report_id}Not exercised hereUpdate a saved report's name or definition.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| report_id | string(uuid) | required |
Request body (required)
Untyped Dict[str, Any] body — there is no Pydantic model, so these are the field names the handler actually reads.
configdataset
Values in the request below are typed placeholders, not sample data.
Request
curl -X PATCH 'https://api.vxcloud.io/api/v1/salesshift/reports/{report_id}' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "config": "<value>", "dataset": "<value>" }'Response · 200
{
"data": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 404 | Report not found |
| 400 | computed at runtime: str(exc) |
DELETE/api/v1/salesshift/reports/{report_id}Called liveDelete a report along with its dashboard widgets and schedules.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| report_id | string(uuid) | required |
Request
curl -X DELETE 'https://api.vxcloud.io/api/v1/salesshift/reports/{report_id}' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"deleted": "bool"
}GET/api/v1/salesshift/reports/{report_id}/exportCalled liveRun a saved report and return it as a downloadable file.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| report_id | string(uuid) | required |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/reports/{report_id}/export' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
"CSV text: a header row of column labels, then one row per group."Errors
| Status | detail |
|---|---|
| 404 | Report not found |
| 400 | computed at runtime: str(exc) |
POST/api/v1/salesshift/reports/{report_id}/scheduleNot exercised hereSchedule recurring delivery of a saved report.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| report_id | string(uuid) | required |
Request body (required) — ScheduleIn
| Field | Type | Required | Notes |
|---|---|---|---|
| frequency | string | optional | Default "weekly". |
| hour_utc | integer | optional | Default 7. |
| weekday | integer? | optional | |
| day_of_month | integer? | optional | |
| recipients | string | optional | Default "". |
| format | string | optional | Default "csv". |
| is_active | boolean | optional | Default true. |
Values in the request below are typed placeholders, not sample data.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/reports/{report_id}/schedule' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "frequency": "weekly", "hour_utc": 7, "weekday": 0, "day_of_month": 0, "recipients": "", "format": "csv", "is_active": true }'Response · 201
{
"data": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 404 | Report not found |
| 400 | At least one recipient is required |
GET/api/v1/salesshift/reports/{report_id}/schedulesNot exercised hereThe delivery schedules attached to one report.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| report_id | string(uuid) | required |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/reports/{report_id}/schedules' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"success": "…"
}GET/api/v1/salesshift/reports/datasetsCalled liveWhat the builder UI renders.
What the builder UI renders. Adding a dataset server-side is enough — the front end has no hardcoded field list.
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/reports/datasets' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": [
{
"key": "str",
"label": "str",
"description": "str",
"default_date_field": "str",
"fields": [
"...",
"...x16"
]
},
"...x10"
]
}POST/api/v1/salesshift/reports/runCalled liveRun a report definition without saving it.
Request body (required)
Untyped Dict[str, Any] body — there is no Pydantic model, so these are the field names the handler actually reads.
configdataset
The body in the request below is the exact one sent during verification.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/reports/run' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "dataset": "contacts", "config": { "metrics": [ { "agg": "count" } ] } }'Response · 200
{
"detail": "str"
}Errors
| Status | detail |
|---|---|
| 400 | computed at runtime: str(exc) |