Skip to content
SSalesShiftDocs
API reference

Campaigns

One-off email campaigns, templates, audience resolution, test sends and sending.

15 endpoints· 5 called live· 10 not exercised here· verified against http://127.0.0.1:8741

15 endpoints

GET/api/v1/salesshift/campaignsCalled liveThe organization's campaigns with their tracking rollups.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+custom

Request

curl
curl 'https://api.vxcloud.io/api/v1/salesshift/campaigns' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 200

Observed shape
{
  "success": "bool",
  "data": [
    {
      "id": "str",
      "name": "str",
      "status": "str",
      "subject": "str",
      "body_html": "str",
      "template_key": "str",
      "from_label": "str",
      "sender_account_id": "null",
      "sender_integration_id": "null",
      "from_name": "str",
      "from_email": "str",
      "reply_to": "str",
      "list_ids": [
        "<empty list>"
      ],
      "contact_ids": [
        "...",
        "...x2"
      ],
      "send_at": "null",
      "sent_at": "str",
      "total_recipients": "int",
      "sent_count": "int",
      "failed_count": "int",
      "suppressed_count": "int",
      "error": "null",
      "created_at": "str",
      "opened": "int",
      "replied": "int",
      "clicked": "int"
    },
    "...x2"
  ],
  "cap": "int"
}
Observed on 2026-08-06 — keys are real, values are the types that came back.
#get-api-v1-salesshift-campaignscampaigns_router · vxcloud_fastapiclient/app/services/salesshift/campaigns_router.py:747Called against http://127.0.0.1:8741 on 2026-08-06 with a real JWT; the response matched the shape recorded below.
POST/api/v1/salesshift/campaignsNot exercised hereCreate a campaign after validating the sender and resolving the audience.
Auth
get_org_user
Scope
organization
Success
201 · application/json
Envelope
success+data

Request body (required) — CampaignIn

FieldTypeRequiredNotes
namestringrequired≤ 255 chars.
subjectstringoptionalDefault "".
body_htmlstringoptionalDefault "".
template_keystring?optional
list_idsstring(uuid)[]optionalDefault [].
contact_idsstring(uuid)[]optionalDefault [].
sender_account_idstring(uuid)?optional
sender_integration_idstring(uuid)?optional
from_namestringoptionalDefault "".
from_emailstringoptionalDefault "".
reply_tostringoptionalDefault "".

Values in the request below are typed placeholders, not sample data.

Request

curl
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/campaigns' \
  -H "Authorization: Bearer $SS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "name": "<string>", "subject": "", "body_html": "", "template_key": "<string>", "list_ids": [], "contact_ids": [], "sender_account_id": "<string(uuid)>", "sender_integration_id": "<string(uuid)>", "from_name": "", "from_email": "", "reply_to": "" }'

Response · 201

Top-level keys
{
  "data": "…",
  "success": "…"
}
Top-level keys read from the handler's return statements.
#post-api-v1-salesshift-campaignscampaigns_router · vxcloud_fastapiclient/app/services/salesshift/campaigns_router.py:762Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
GET/api/v1/salesshift/campaigns/{campaign_id}Called liveOne campaign with its stats and per-recipient tracking rows.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+custom

Path parameters

NameTypeRequiredNotes
campaign_idstring(uuid)required

Request

curl
curl 'https://api.vxcloud.io/api/v1/salesshift/campaigns/{campaign_id}' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 200

Observed shape
{
  "success": "bool",
  "data": {
    "id": "str",
    "name": "str",
    "status": "str",
    "subject": "str",
    "body_html": "str",
    "template_key": "str",
    "from_label": "str",
    "sender_account_id": "null",
    "sender_integration_id": "null",
    "from_name": "str",
    "from_email": "str",
    "reply_to": "str",
    "list_ids": [
      "<empty list>"
    ],
    "contact_ids": [
      "str",
      "...x2"
    ],
    "send_at": "null",
    "sent_at": "str",
    "total_recipients": "int",
    "sent_count": "int",
    "failed_count": "int",
    "suppressed_count": "int",
    "error": "null",
    "created_at": "str",
    "opened": "int",
    "replied": "int",
    "clicked": "int"
  },
  "recipients": [
    {
      "to_email": "str",
      "status": "str",
      "opened": "bool",
      "replied": "bool",
      "error": "null",
      "sent_at": "str"
    },
    "...x2"
  ]
}
Observed on 2026-08-06 — keys are real, values are the types that came back.
#get-api-v1-salesshift-campaigns-campaign-idcampaigns_router · vxcloud_fastapiclient/app/services/salesshift/campaigns_router.py:805Called against http://127.0.0.1:8741 on 2026-08-06 with a real JWT; the response matched the shape recorded below.
PATCH/api/v1/salesshift/campaigns/{campaign_id}Not exercised hereEdit a campaign; only drafts and scheduled campaigns can be edited.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+data

Path parameters

NameTypeRequiredNotes
campaign_idstring(uuid)required

Request body (required) — CampaignIn

FieldTypeRequiredNotes
namestringrequired≤ 255 chars.
subjectstringoptionalDefault "".
body_htmlstringoptionalDefault "".
template_keystring?optional
list_idsstring(uuid)[]optionalDefault [].
contact_idsstring(uuid)[]optionalDefault [].
sender_account_idstring(uuid)?optional
sender_integration_idstring(uuid)?optional
from_namestringoptionalDefault "".
from_emailstringoptionalDefault "".
reply_tostringoptionalDefault "".

Values in the request below are typed placeholders, not sample data.

Request

curl
curl -X PATCH 'https://api.vxcloud.io/api/v1/salesshift/campaigns/{campaign_id}' \
  -H "Authorization: Bearer $SS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "name": "<string>", "subject": "", "body_html": "", "template_key": "<string>", "list_ids": [], "contact_ids": [], "sender_account_id": "<string(uuid)>", "sender_integration_id": "<string(uuid)>", "from_name": "", "from_email": "", "reply_to": "" }'

Response · 200

Top-level keys
{
  "data": "…",
  "success": "…"
}
Top-level keys read from the handler's return statements.

Errors

Statusdetail
400Only drafts can be edited
#patch-api-v1-salesshift-campaigns-campaign-idcampaigns_router · vxcloud_fastapiclient/app/services/salesshift/campaigns_router.py:832Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
DELETE/api/v1/salesshift/campaigns/{campaign_id}Not exercised hereDelete a campaign.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+custom

Path parameters

NameTypeRequiredNotes
campaign_idstring(uuid)required

Request

curl
curl -X DELETE 'https://api.vxcloud.io/api/v1/salesshift/campaigns/{campaign_id}' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 200

Top-level keys
{
  "success": "…"
}
Top-level keys read from the handler's return statements.
#delete-api-v1-salesshift-campaigns-campaign-idcampaigns_router · vxcloud_fastapiclient/app/services/salesshift/campaigns_router.py:865Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
POST/api/v1/salesshift/campaigns/{campaign_id}/sendNot exercised hereSend or schedule a campaign to its resolved audience.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+custom

Path parameters

NameTypeRequiredNotes
campaign_idstring(uuid)required

Request body (required) — app__services__salesshift__campaigns_router__SendIn

FieldTypeRequiredNotes
send_atstring(date-time)?optional

Values in the request below are typed placeholders, not sample data.

Request

curl
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/campaigns/{campaign_id}/send' \
  -H "Authorization: Bearer $SS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "send_at": "<string(date-time)>" }'

Response · 200

Top-level keys
{
  "failed": "…",
  "send_at": "…",
  "sent": "…",
  "status": "…",
  "success": "…",
  "suppressed": "…"
}
Top-level keys read from the handler's return statements.

Errors

Statusdetail
400Campaign already {...}
400Campaign needs a subject and a body
#post-api-v1-salesshift-campaigns-campaign-id-sendcampaigns_router · vxcloud_fastapiclient/app/services/salesshift/campaigns_router.py:989Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
POST/api/v1/salesshift/campaigns/{campaign_id}/test-sendNot exercised hereSend one preview copy to a chosen address using a transient probe contact.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+custom

Path parameters

NameTypeRequiredNotes
campaign_idstring(uuid)required

Request body (required) — TestSendIn

FieldTypeRequiredNotes
to_emailstringrequired

Values in the request below are typed placeholders, not sample data.

Request

curl
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/campaigns/{campaign_id}/test-send' \
  -H "Authorization: Bearer $SS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "to_email": "<string>" }'

Response · 200

Top-level keys
{
  "error": "…",
  "provider": "…",
  "status": "…",
  "success": "…"
}
Top-level keys read from the handler's return statements.

Errors

Statusdetail
400computed at runtime: str(exc)
#post-api-v1-salesshift-campaigns-campaign-id-test-sendcampaigns_router · vxcloud_fastapiclient/app/services/salesshift/campaigns_router.py:893Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
POST/api/v1/salesshift/campaigns/{campaign_id}/unscheduleNot exercised herePut a scheduled campaign back into draft.

Put a scheduled campaign back into draft. Scheduling was a one-way door: `process_due_campaigns` would fire it and the UI offered no way to stop it. Clearing `send_at` with the status is what keeps the dispatch loop from picking it up again.

Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+data

Path parameters

NameTypeRequiredNotes
campaign_idstring(uuid)required

Request

curl
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/campaigns/{campaign_id}/unschedule' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 200

Top-level keys
{
  "data": "…",
  "success": "…"
}
Top-level keys read from the handler's return statements.

Errors

Statusdetail
400Campaign is {...}, not scheduled
#post-api-v1-salesshift-campaigns-campaign-id-unschedulecampaigns_router · vxcloud_fastapiclient/app/services/salesshift/campaigns_router.py:1015Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
POST/api/v1/salesshift/campaigns/audience-previewCalled liveResolve lists and contact ids to a sendable audience, reporting what was dropped and the cap.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+custom

Request body (required) — AudiencePreviewIn

FieldTypeRequiredNotes
list_idsstring(uuid)[]optionalDefault [].
contact_idsstring(uuid)[]optionalDefault [].

The body in the request below is the exact one sent during verification.

Request

curl
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/campaigns/audience-preview' \
  -H "Authorization: Bearer $SS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "list_ids": [], "contact_ids": [] }'

Response · 200

Observed shape
{
  "success": "bool",
  "count": "int",
  "dropped": "int",
  "cap": "int",
  "over_cap": "int",
  "sample": [
    "<empty list>"
  ]
}
Observed on 2026-08-06 — keys are real, values are the types that came back.
#post-api-v1-salesshift-campaigns-audience-previewcampaigns_router · vxcloud_fastapiclient/app/services/salesshift/campaigns_router.py:614Called against http://127.0.0.1:8741 on 2026-08-06 with a real JWT; the response matched the shape recorded below.
GET/api/v1/salesshift/campaigns/sendersCalled liveAvailable sending servers: every active BYOK email integration (multi-SMTP: one entry per configured server, default first) + every active connected mailbox (each one a full SMTP identity).

Available sending servers: every active BYOK email integration (multi-SMTP: one entry per configured server, default first) + every active connected mailbox (each one a full SMTP identity).

Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+data

Request

curl
curl 'https://api.vxcloud.io/api/v1/salesshift/campaigns/senders' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 200

Observed shape
{
  "success": "bool",
  "data": [
    {
      "id": "str",
      "kind": "str",
      "label": "str",
      "from_email": "str",
      "from_name": "str",
      "reply_to": "str",
      "is_default": "bool",
      "provider": "str"
    },
    "...x7"
  ]
}
Observed on 2026-08-06 — keys are real, values are the types that came back.
#get-api-v1-salesshift-campaigns-senderscampaigns_router · vxcloud_fastapiclient/app/services/salesshift/campaigns_router.py:640Called against http://127.0.0.1:8741 on 2026-08-06 with a real JWT; the response matched the shape recorded below.
GET/api/v1/salesshift/campaigns/templatesCalled liveBuilt-in email templates plus the organization's saved ones.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+custom

Request

curl
curl 'https://api.vxcloud.io/api/v1/salesshift/campaigns/templates' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 200

Observed shape
{
  "success": "bool",
  "builtin": [
    {
      "key": "str",
      "name": "str",
      "category": "str",
      "description": "str",
      "subject": "str",
      "body_html": "str"
    },
    "...x6"
  ],
  "custom": [
    {
      "key": "str",
      "id": "str",
      "name": "str",
      "category": "str",
      "description": "str",
      "subject": "str",
      "body_html": "str",
      "created_at": "str",
      "updated_at": "str"
    },
    "...x11"
  ]
}
Observed on 2026-08-06 — keys are real, values are the types that came back.
#get-api-v1-salesshift-campaigns-templatescampaigns_router · vxcloud_fastapiclient/app/services/salesshift/campaigns_router.py:511Called against http://127.0.0.1:8741 on 2026-08-06 with a real JWT; the response matched the shape recorded below.
POST/api/v1/salesshift/campaigns/templatesNot exercised hereSave a custom email template.
Auth
get_org_user
Scope
organization
Success
201 · application/json
Envelope
success+custom

Request body (required) — TemplateIn

FieldTypeRequiredNotes
namestringrequired
categorystringoptionalDefault "Custom".
subjectstringoptionalDefault "".
body_htmlstringoptionalDefault "".

Values in the request below are typed placeholders, not sample data.

Request

curl
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/campaigns/templates' \
  -H "Authorization: Bearer $SS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "name": "<string>", "category": "Custom", "subject": "", "body_html": "" }'

Response · 201

Top-level keys
{
  "data": "…",
  "id": "…",
  "success": "…"
}
Top-level keys read from the handler's return statements.
#post-api-v1-salesshift-campaigns-templatescampaigns_router · vxcloud_fastapiclient/app/services/salesshift/campaigns_router.py:525Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
PUT/api/v1/salesshift/campaigns/templates/{template_id}Not exercised hereUpdate a saved email template.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+data

Path parameters

NameTypeRequiredNotes
template_idstring(uuid)required

Request body (required) — TemplateUpdateIn

FieldTypeRequiredNotes
namestring?optional
categorystring?optional
subjectstring?optional
body_htmlstring?optional

Values in the request below are typed placeholders, not sample data.

Request

curl
curl -X PUT 'https://api.vxcloud.io/api/v1/salesshift/campaigns/templates/{template_id}' \
  -H "Authorization: Bearer $SS_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "name": "<string>", "category": "<string>", "subject": "<string>", "body_html": "<string>" }'

Response · 200

Top-level keys
{
  "data": "…",
  "success": "…"
}
Top-level keys read from the handler's return statements.
#put-api-v1-salesshift-campaigns-templates-template-idcampaigns_router · vxcloud_fastapiclient/app/services/salesshift/campaigns_router.py:576Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
DELETE/api/v1/salesshift/campaigns/templates/{template_id}Not exercised hereDelete a saved email template.
Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+custom

Path parameters

NameTypeRequiredNotes
template_idstring(uuid)required

Request

curl
curl -X DELETE 'https://api.vxcloud.io/api/v1/salesshift/campaigns/templates/{template_id}' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 200

Top-level keys
{
  "success": "…"
}
Top-level keys read from the handler's return statements.
#delete-api-v1-salesshift-campaigns-templates-template-idcampaigns_router · vxcloud_fastapiclient/app/services/salesshift/campaigns_router.py:598Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.
POST/api/v1/salesshift/campaigns/templates/seedNot exercised hereDrop the starter 1:1 sales library into this org.

Drop the starter 1:1 sales library into this org. Idempotent — a template whose name already exists in the org is skipped, never duplicated or overwritten (the rep's edits win).

Auth
get_org_user
Scope
organization
Success
200 · application/json
Envelope
success+custom

Request

curl
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/campaigns/templates/seed' \
  -H "Authorization: Bearer $SS_TOKEN"

Response · 200

Top-level keys
{
  "created": "…",
  "data": "…",
  "skipped": "…",
  "success": "…"
}
Top-level keys read from the handler's return statements.
#post-api-v1-salesshift-campaigns-templates-seedcampaigns_router · vxcloud_fastapiclient/app/services/salesshift/campaigns_router.py:541Implemented and read in source for this inventory, but not exercised against a running server here. Treat as undemonstrated until someone calls it.