Deliverability
Sending pool, per-inbox caps and health, domain auth checks, seed list and placement tests.
13 endpoints· 5 called live· verified against http://127.0.0.1:8741
13 endpoints
GET/api/v1/salesshift/deliverability/domain/{domain}Verified in sessionSPF / DKIM / DMARC / MX / blocklist for one domain.
SPF / DKIM / DMARC / MX / blocklist for one domain. Served from cache while it is fresh; otherwise the node re-queries DNS. If the node is unreachable and a previous answer exists, that answer comes back flagged ``stale`` with the node error attached — a six-hour-old DMARC record is useful and clearly labelled, an invented one is not.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| domain | string | required |
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| refresh | boolean | optional | Ignore the cache and re-query DNS now Default false. |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/deliverability/domain/{domain}' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 400 | Not a valid domain: {...} |
| 502 | DNS engine unavailable and nothing cached for {...}: {...} |
GET/api/v1/salesshift/deliverability/domainsCalled liveEvery sending domain the org's mailboxes use, with the last DNS answer for each.
Every sending domain the org's mailboxes use, with the last DNS answer for each. Domains with no ``checked_at`` have never been checked — the UI says exactly that instead of showing a green tick by default.
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/deliverability/domains' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": {
"domains": [
{
"domain": "...",
"checked_at": "...",
"age_seconds": "...",
"issues": "...",
"status": "..."
},
"...x2"
]
}
}GET/api/v1/salesshift/deliverability/inboxesCalled liveThe sending pool: every connected mailbox with its cap, ramp position, health, and — when it is not sending — the reason.
The sending pool: every connected mailbox with its cap, ramp position, health, and — when it is not sending — the reason. The health pass does NOT run inline. It writes a snapshot row per mailbox into an append-only table, and making a GET that the UI fires on mount and after every pause/resume wait for that write couples page latency to write volume — the page then times out in the browser and shows nothing at all, which is worse than showing slightly older numbers. So this returns the last computed health immediately and says, in ``health_status``, exactly when it was computed and whether a refresh is running. That is the whole bargain: serving a previous computation is fine, serving it as though it were current is not.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| recompute | boolean | optional | Ask for a health refresh; it runs in the background and this response reports when the health it shows was actually computed Default true. |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/deliverability/inboxes' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": {
"rotation_enabled": "bool",
"rotation_status": "str",
"inbox_count": "int",
"pooled_count": "int",
"sendable_count": "int",
"paused_count": "int",
"needs_reconnect_count": "int",
"capacity_today": "int",
"remaining_today": "int",
"paused_capacity_today": "int",
"reconnect_capacity_today": "int",
"org_daily_ceiling": "int",
"org_sent_today": "int",
"next_sender": "str",
"next_sender_blocked_reason": "null",
"next_retry_after": "null",
"health_status": {
"computed_at": "str",
"age_seconds": "int",
"fresh": "bool",
"refreshing": "bool",
"refresh_floor_seconds": "int",
"note": "str"
},
"health_formula": {
"base_score": "float",
"window_days": "int",
"min_sample_for_score": "int",
"penalties": {
"complaint_rate": "...",
"bounce_rate": "...",
"failure_rate": "..."
},
"engagement_bonus": {
"max_points": "...",
"target": "...",
"formula": "...",
"why": "..."
},
"grades": {
"excellent": "...",
"good": "...",
"at_risk": "..."
},
"auto_pause": {
"complaint_rate": "...",
"bounce_rate": "...",
"resume": "..."
}
},
"inboxes": [
{
"id": "...",
"email": "...",
"display_name": "...",
"provider": "...",
"is_active": "...",
"in_pool": "...",
"weight": "...",
"daily_cap": "...",
"effective_cap_today": "...",
"sendable": "...",
"ramp": "...",
"send_gap_seconds": "...",
"sent_today": "...",
"remaining_today": "...",
"headroom_if_resumed": "...",
"auth": "...",
"needs_reconnect": "...",
"paused": "...",
"pause": "...",
"last_resume": "...",
"health": "...",
"selector": "..."
},
"...x6"
]
}
}PATCH/api/v1/salesshift/deliverability/inboxes/{inbox_id}Verified in sessionChange one mailbox's pool policy.
Change one mailbox's pool policy. Pause state is not editable here — it has its own endpoints so that lifting a pause always records who did.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| inbox_id | string(uuid) | required |
Request body (required) — InboxPolicyPatch
| Field | Type | Required | Notes |
|---|---|---|---|
| in_pool | boolean? | optional | |
| weight | number? | optional | |
| daily_cap | integer? | optional | |
| ramp_start_date | string? | optional | YYYY-MM-DD, or empty string to clear the ramp |
| ramp_initial | integer? | optional | |
| ramp_daily_increment | integer? | optional | |
| send_gap_seconds | integer? | optional |
Values in the request below are typed placeholders, not sample data.
Request
curl -X PATCH 'https://api.vxcloud.io/api/v1/salesshift/deliverability/inboxes/{inbox_id}' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "in_pool": false, "weight": 0, "daily_cap": 0, "ramp_start_date": "<string>", "ramp_initial": 0, "ramp_daily_increment": 0, "send_gap_seconds": 0 }'Response · 200
{
"data": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 400 | No fields to update |
| 404 | Mailbox not found in this organization |
POST/api/v1/salesshift/deliverability/inboxes/{inbox_id}/pauseVerified in sessionPause one mailbox in the sending pool with a recorded reason.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| inbox_id | string(uuid) | required |
Request body (optional)
Untyped Dict[str, Any] body — there is no Pydantic model, so these are the field names the handler actually reads.
reason
Values in the request below are typed placeholders, not sample data.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/deliverability/inboxes/{inbox_id}/pause' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "reason": "<value>" }'Response · 200
{
"data": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 404 | Mailbox not found in this organization |
POST/api/v1/salesshift/deliverability/inboxes/{inbox_id}/resumeVerified in sessionPut a mailbox back in the rotation.
Put a mailbox back in the rotation. This is the ONLY way an auto-pause clears. The health pass will re-pause it on the next run if the numbers have not moved, which is the point: resuming is an assertion that something was fixed, and if nothing was, the guard fires again instead of quietly letting the mailbox burn.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| inbox_id | string(uuid) | required |
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/deliverability/inboxes/{inbox_id}/resume' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"data": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 404 | Mailbox not found in this organization |
POST/api/v1/salesshift/deliverability/placement-testVerified in sessionSend a probe to the org's seed list and report where it landed.
Send a probe to the org's seed list and report where it landed. Behaviour when there is no seed list: status ``no_seed_list`` and an explanation. That is the honest answer — a placement test with nothing to send to has no result, and printing a made-up inbox percentage would be worse than printing nothing. Placement itself is only claimed for seeds that are mailboxes this org has connected, because reading the destination folder is the only way to know. Every other seed is recorded as sent with placement null.
Request body (optional)
Untyped Dict[str, Any] body — there is no Pydantic model, so these are the field names the handler actually reads.
inbox_id
Values in the request below are typed placeholders, not sample data.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/deliverability/placement-test' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "inbox_id": "<value>" }'Response · 200
{
"data": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 400 | No mailbox available to send from |
| 404 | Mailbox not found in this organization |
| 400 | No mailbox available to send from — pass inbox_id, or add an active unpaused mailbox to the pool. |
GET/api/v1/salesshift/deliverability/placement-testsCalled liveRecent inbox-placement tests and their per-seed results.
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| limit | integer | optional | Default 20. max 100. |
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/deliverability/placement-tests' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": {
"tests": [
{
"from_email": "...",
"subject": "...",
"status": "...",
"seed_count": "...",
"sent_count": "...",
"failed_count": "...",
"results": "...",
"note": "...",
"id": "...",
"created_at": "...",
"completed_at": "..."
},
"...x10"
]
}
}GET/api/v1/salesshift/deliverability/seed-listCalled liveThe organization's seed addresses, joined to any connected webmail account.
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/deliverability/seed-list' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": {
"seeds": [
{
"id": "...",
"email": "...",
"provider": "...",
"is_active": "...",
"notes": "...",
"placement_readable": "..."
},
"...x1"
],
"configured": "bool",
"readable_count": "int",
"note": "str"
}
}POST/api/v1/salesshift/deliverability/seed-listVerified in sessionAdd a seed address used by placement tests.
Request body (required) — SeedAddress
| Field | Type | Required | Notes |
|---|---|---|---|
| string | required | ||
| provider | string | optional | Default "other". |
| notes | string? | optional |
Values in the request below are typed placeholders, not sample data.
Request
curl -X POST 'https://api.vxcloud.io/api/v1/salesshift/deliverability/seed-list' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "email": "<string>", "provider": "other", "notes": "<string>" }'Response · 200
{
"data": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 400 | Not a valid email address |
DELETE/api/v1/salesshift/deliverability/seed-list/{seed_id}Verified in sessionRemove a seed address.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
| seed_id | string(uuid) | required |
Request
curl -X DELETE 'https://api.vxcloud.io/api/v1/salesshift/deliverability/seed-list/{seed_id}' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "…"
}Errors
| Status | detail |
|---|---|
| 404 | Seed address not found |
GET/api/v1/salesshift/deliverability/settingsCalled liveSending-pool settings: rotation flag, health window and the platform defaults.
Request
curl 'https://api.vxcloud.io/api/v1/salesshift/deliverability/settings' \
-H "Authorization: Bearer $SS_TOKEN"Response · 200
{
"success": "bool",
"data": {
"rotation_enabled": "bool",
"health_window_days": "int",
"defaults": {
"daily_cap": "int",
"ramp_initial": "int",
"ramp_daily_increment": "int",
"send_gap_seconds": "int"
}
}
}PATCH/api/v1/salesshift/deliverability/settingsVerified in sessionOrg-level pool switches.
Org-level pool switches. Rotation ships OFF. Turning it on changes which address a tenant's mail comes from, and doing that to a live domain without being asked is exactly how a sending reputation gets destroyed — so it is an explicit decision, made once, by someone who knows their mailboxes are configured.
Request body (required) — PoolSettingsPatch
| Field | Type | Required | Notes |
|---|---|---|---|
| rotation_enabled | boolean? | optional | |
| health_window_days | integer? | optional |
Values in the request below are typed placeholders, not sample data.
Request
curl -X PATCH 'https://api.vxcloud.io/api/v1/salesshift/deliverability/settings' \
-H "Authorization: Bearer $SS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "rotation_enabled": false, "health_window_days": 0 }'Response · 200
{
"data": "…",
"success": "…"
}Errors
| Status | detail |
|---|---|
| 400 | No settings to update |