SSpiderIQ
SSpiderIQ

Docs / api-reference/send-broadcasts

Send Broadcasts

12 endpoints from the published OpenAPI import.

GET/api/v1/dashboard/send/broadcasts/paste-consent

This workspace's consent basis for pasted address lists

Full history, newest first, with the active declaration called out.

Revoked declarations are kept and returned: "you have no basis" and "you revoked your basis last Tuesday" are different facts, and only the second one tells an operator what happened to their composer.

Try it

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/send/broadcasts/paste-consent' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/send/broadcasts/paste-consent",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/send/broadcasts/paste-consent", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://spideriq.ai/api/v1/dashboard/send/broadcasts/paste-consent", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
POST/api/v1/dashboard/send/broadcasts/paste-consent

Declare (or supersede) the consent basis for pasted address lists

Record what lawful basis this workspace relies on for pasted addresses.

Declaring again supersedes: the previous declaration is revoked in the same transaction, so a workspace has at most one active basis and its history stays readable.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/send/broadcasts/paste-consent' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "basis": "express_consent",
  "source_description": "string",
  "evidence_url": "string"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/send/broadcasts/paste-consent",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"basis": "express_consent", "source_description": "string", "evidence_url": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/send/broadcasts/paste-consent", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"basis": "express_consent", "source_description": "string", "evidence_url": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"basis": "express_consent", "source_description": "string", "evidence_url": "string"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/send/broadcasts/paste-consent", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
201Successful Response
422Validation Error
DELETE/api/v1/dashboard/send/broadcasts/paste-consent

Revoke the consent basis for pasted address lists

Withdraw the active declaration.

Takes effect at both doors immediately — no new paste broadcast can be composed, and any already-composed paste draft is refused at queue time. Messages already in send_queue are not retracted; that is the same boundary DELETE /{broadcast_id} draws.

Try it

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/send/broadcasts/paste-consent' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/send/broadcasts/paste-consent",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/send/broadcasts/paste-consent", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://spideriq.ai/api/v1/dashboard/send/broadcasts/paste-consent", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
204Successful Response
POST/api/v1/dashboard/send/broadcasts/audience/preview

Resolve an audience query to a deliverable count

Resolve WITHOUT persisting anything.

Always reports the subtractions (suppressed / duplicates / invalid) so a shrinking audience reads as the deliverability guard working rather than as missing data. suppression_checked=false means the count is provisional — the queue path refuses outright in that state.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/send/broadcasts/audience/preview' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "mode": "crm",
  "board_id": "string",
  "email_status": "valid",
  "require_first_name": false,
  "topics": [
    "string"
  ],
  "addresses": [
    "string"
  ]
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/send/broadcasts/audience/preview",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"mode": "crm", "board_id": "string", "email_status": "valid", "require_first_name": false, "topics": ["string"], "addresses": ["string"]},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/send/broadcasts/audience/preview", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"mode": "crm", "board_id": "string", "email_status": "valid", "require_first_name": false, "topics": ["string"], "addresses": ["string"]})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"mode": "crm", "board_id": "string", "email_status": "valid", "require_first_name": false, "topics": ["string"], "addresses": ["string"]}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/send/broadcasts/audience/preview", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
422Validation Error
POST/api/v1/dashboard/send/broadcasts/preview

Render a draft as a recipient will receive it

Server-side on purpose: this uses the SAME markdown renderer as fan-out, so the preview cannot drift from the message that actually goes out.

Since CAN-SPAM.2 it also reads the caller's own brand — the tenant scope is load-bearing here, not merely a permission check, because the footer carries that brand's postal address and a preview rendered under someone else's would be showing an address this send will never carry.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/send/broadcasts/preview' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "subject_template": "",
  "body_md": "",
  "sample": {
    "email": "string",
    "first_name": "string",
    "full_name": "string",
    "current_company": "string"
  }
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/send/broadcasts/preview",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"subject_template": "", "body_md": "", "sample": {"email": "string", "first_name": "string", "full_name": "string", "current_company": "string"}},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/send/broadcasts/preview", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"subject_template": "", "body_md": "", "sample": {"email": "string", "first_name": "string", "full_name": "string", "current_company": "string"}})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"subject_template": "", "body_md": "", "sample": {"email": "string", "first_name": "string", "full_name": "string", "current_company": "string"}}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/send/broadcasts/preview", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/dashboard/send/broadcasts/capacity

Sending capacity and drain estimate for the selected sources

Combined effective (warmup-aware) daily cap, remaining capacity today, and how long the audience takes to drain at that rate.

Parameters

NameInTypeRequiredDescription
mailbox_idsqueryanyfalseComma-separated mailbox ids. Omitted = every source the tenant owns.
audience_sizequeryintegerfalse
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/send/broadcasts/capacity' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/send/broadcasts/capacity",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/send/broadcasts/capacity", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://spideriq.ai/api/v1/dashboard/send/broadcasts/capacity", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/dashboard/send/broadcasts

List broadcasts

Parameters

NameInTypeRequiredDescription
limitqueryintegerfalse
offsetqueryintegerfalse
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/send/broadcasts' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/send/broadcasts",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/send/broadcasts", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://spideriq.ai/api/v1/dashboard/send/broadcasts", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
422Validation Error
POST/api/v1/dashboard/send/broadcasts

Create a broadcast draft

Creates a draft. Nothing is enqueued and no mail can leave until POST /{id}/queue — mirroring the admin composer's draft→publish split.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/send/broadcasts' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Untitled broadcast",
  "subject_template": "",
  "preheader": "string",
  "body_md": "",
  "from_name": "string",
  "reply_to": "string",
  "audience": {
    "mode": "crm",
    "board_id": "string",
    "email_status": "valid",
    "require_first_name": false,
    "topics": [
      "string"
    ],
    "addresses": [
      "string"
    ]
  },
  "source_mailbox_ids": [
    0
  ],
  "scheduled_at": "2026-01-01T00:00:00Z"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/send/broadcasts",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "Untitled broadcast", "subject_template": "", "preheader": "string", "body_md": "", "from_name": "string", "reply_to": "string", "audience": {"mode": "crm", "board_id": "string", "email_status": "valid", "require_first_name": false, "topics": ["string"], "addresses": ["string"]}, "source_mailbox_ids": [0], "scheduled_at": "2026-01-01T00:00:00Z"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/send/broadcasts", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "Untitled broadcast", "subject_template": "", "preheader": "string", "body_md": "", "from_name": "string", "reply_to": "string", "audience": {"mode": "crm", "board_id": "string", "email_status": "valid", "require_first_name": false, "topics": ["string"], "addresses": ["string"]}, "source_mailbox_ids": [0], "scheduled_at": "2026-01-01T00:00:00Z"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "Untitled broadcast", "subject_template": "", "preheader": "string", "body_md": "", "from_name": "string", "reply_to": "string", "audience": {"mode": "crm", "board_id": "string", "email_status": "valid", "require_first_name": false, "topics": ["string"], "addresses": ["string"]}, "source_mailbox_ids": [0], "scheduled_at": "2026-01-01T00:00:00Z"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/send/broadcasts", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
201Successful Response
422Validation Error
GET/api/v1/dashboard/send/broadcasts/{broadcast_id}

Get a broadcast

Includes live delivery progress aggregated from send_queue.

Parameters

NameInTypeRequiredDescription
broadcast_idpathstringtrue
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/send/broadcasts/{broadcast_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/send/broadcasts/{broadcast_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/send/broadcasts/{broadcast_id}", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://spideriq.ai/api/v1/dashboard/send/broadcasts/{broadcast_id}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
422Validation Error
PATCH/api/v1/dashboard/send/broadcasts/{broadcast_id}

Update a draft

True PATCH — only the fields present are written. Drafts only: editing a queued broadcast would change what the composer shows without changing a single already-queued message.

Parameters

NameInTypeRequiredDescription
broadcast_idpathstringtrue
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/send/broadcasts/{broadcast_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "subject_template": "string",
  "preheader": "string",
  "body_md": "string",
  "from_name": "string",
  "reply_to": "string",
  "audience": {
    "mode": "crm",
    "board_id": "string",
    "email_status": "valid",
    "require_first_name": false,
    "topics": [
      "string"
    ],
    "addresses": [
      "string"
    ]
  },
  "source_mailbox_ids": [
    0
  ],
  "scheduled_at": "2026-01-01T00:00:00Z"
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/send/broadcasts/{broadcast_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "subject_template": "string", "preheader": "string", "body_md": "string", "from_name": "string", "reply_to": "string", "audience": {"mode": "crm", "board_id": "string", "email_status": "valid", "require_first_name": false, "topics": ["string"], "addresses": ["string"]}, "source_mailbox_ids": [0], "scheduled_at": "2026-01-01T00:00:00Z"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/send/broadcasts/{broadcast_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "subject_template": "string", "preheader": "string", "body_md": "string", "from_name": "string", "reply_to": "string", "audience": {"mode": "crm", "board_id": "string", "email_status": "valid", "require_first_name": false, "topics": ["string"], "addresses": ["string"]}, "source_mailbox_ids": [0], "scheduled_at": "2026-01-01T00:00:00Z"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "subject_template": "string", "preheader": "string", "body_md": "string", "from_name": "string", "reply_to": "string", "audience": {"mode": "crm", "board_id": "string", "email_status": "valid", "require_first_name": false, "topics": ["string"], "addresses": ["string"]}, "source_mailbox_ids": [0], "scheduled_at": "2026-01-01T00:00:00Z"}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/send/broadcasts/{broadcast_id}", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
422Validation Error
DELETE/api/v1/dashboard/send/broadcasts/{broadcast_id}

Cancel a broadcast that has not been fanned out

Already-queued rows are deliberately NOT withdrawn — pulling messages out from under the send loop is a different, riskier operation than abandoning a draft.

Parameters

NameInTypeRequiredDescription
broadcast_idpathstringtrue
Try it
Query

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/send/broadcasts/{broadcast_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/send/broadcasts/{broadcast_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/send/broadcasts/{broadcast_id}", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://spideriq.ai/api/v1/dashboard/send/broadcasts/{broadcast_id}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
204Successful Response
422Validation Error
POST/api/v1/dashboard/send/broadcasts/{broadcast_id}/queue

Fan a broadcast out into the send queue

202 — the rows are enqueued; the send loop delivers them on its own pace.

already_enqueued > 0 is a RESUMED fan-out, not a failure: the enqueue is idempotent per (broadcast, address), so a retry after an interruption fills only the gaps instead of double-sending.

provider_configured=false means the messages are queued and will HOLD at queued until Mailgun credentials exist. That is a deliberate dormant state, reported honestly rather than surfaced as an error or faked as sent.

Parameters

NameInTypeRequiredDescription
broadcast_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/send/broadcasts/{broadcast_id}/queue' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/send/broadcasts/{broadcast_id}/queue",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/send/broadcasts/{broadcast_id}/queue", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/send/broadcasts/{broadcast_id}/queue", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
202Successful Response
422Validation Error