SSpiderIQ
SSpiderIQ

Docs / api-reference/content-studio

Content Studio

234 endpoints from the published OpenAPI import.

GET/api/v1/dashboard/content/pages

List Pages

List all content pages (including drafts). Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

NameInTypeRequiredDescription
pagequeryintegerfalse
page_sizequeryintegerfalse
statusqueryanyfalse
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/pages",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages", {
  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/content/pages", 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/content/pages

Create Page

Create a new content page. Phase 11+12 dry_run/confirm_token gated.

Parameters

NameInTypeRequiredDescription
dry_runquerybooleanfalsePhase 11+12: preview the create and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the create.
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/pages' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "slug": "string",
  "title": "string",
  "description": "string",
  "agent_strategy": "string",
  "agent_flow_id": "string",
  "geo_ai_summary": "string",
  "geo_ai_crawlers": "string",
  "seo_title": "string",
  "seo_description": "string",
  "og_title": "string",
  "og_description": "string",
  "og_image_url": "string",
  "twitter_card": "string",
  "twitter_image_url": "string",
  "canonical_url": "string",
  "robots": "string",
  "keywords": "string",
  "json_ld": {},
  "blocks": [
    {
      "id": "string",
      "type": "hero",
      "data": {},
      "component_slug": "string",
      "component_version": "string",
      "props": {},
      "layout": "string",
      "data_binding": {}
    }
  ],
  "template": "default"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/pages",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"slug": "string", "title": "string", "description": "string", "agent_strategy": "string", "agent_flow_id": "string", "geo_ai_summary": "string", "geo_ai_crawlers": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "blocks": [{"id": "string", "type": "hero", "data": {}, "component_slug": "string", "component_version": "string", "props": {}, "layout": "string", "data_binding": {}}], "template": "default"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"slug": "string", "title": "string", "description": "string", "agent_strategy": "string", "agent_flow_id": "string", "geo_ai_summary": "string", "geo_ai_crawlers": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "blocks": [{"id": "string", "type": "hero", "data": {}, "component_slug": "string", "component_version": "string", "props": {}, "layout": "string", "data_binding": {}}], "template": "default"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"slug": "string", "title": "string", "description": "string", "agent_strategy": "string", "agent_flow_id": "string", "geo_ai_summary": "string", "geo_ai_crawlers": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "blocks": [{"id": "string", "type": "hero", "data": {}, "component_slug": "string", "component_version": "string", "props": {}, "layout": "string", "data_binding": {}}], "template": "default"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/pages", 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/content/pages/{page_id}

Get Page

Get a page by ID. Use ?format=json|yaml|md|llm for agent-friendly responses.

P5: pass ?audit_level=off|errors|warnings|all to control the _page_audit decoration. Default 'warnings' returns errors + warnings in the audit block.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
audit_levelquerystringfalseP5: include a _page_audit block on the response. 'off' skips the auditor entirely (cheapest). 'errors' / 'warnings' / 'all' filter by severity. Default 'warnings' — agent-friendly.
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/{page_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/content/pages/{page_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/content/pages/{page_id}

Update Page

Update a page. Phase 11+12 dry_run/confirm_token gated. P4 lock-aware.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the update and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the update.
forcequerybooleanfalseP4: bypass page lock (super_admin / brand_admin only).
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "agent_strategy": "string",
  "agent_flow_id": "string",
  "geo_ai_summary": "string",
  "geo_ai_crawlers": "string",
  "seo_title": "string",
  "seo_description": "string",
  "og_title": "string",
  "og_description": "string",
  "og_image_url": "string",
  "twitter_card": "string",
  "twitter_image_url": "string",
  "canonical_url": "string",
  "robots": "string",
  "keywords": "string",
  "json_ld": {},
  "title": "string",
  "description": "string",
  "blocks": [
    {
      "id": "string",
      "type": "hero",
      "data": {},
      "component_slug": "string",
      "component_version": "string",
      "props": {},
      "layout": "string",
      "data_binding": {}
    }
  ],
  "template": "string",
  "collection_type": "string"
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"agent_strategy": "string", "agent_flow_id": "string", "geo_ai_summary": "string", "geo_ai_crawlers": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "title": "string", "description": "string", "blocks": [{"id": "string", "type": "hero", "data": {}, "component_slug": "string", "component_version": "string", "props": {}, "layout": "string", "data_binding": {}}], "template": "string", "collection_type": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"agent_strategy": "string", "agent_flow_id": "string", "geo_ai_summary": "string", "geo_ai_crawlers": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "title": "string", "description": "string", "blocks": [{"id": "string", "type": "hero", "data": {}, "component_slug": "string", "component_version": "string", "props": {}, "layout": "string", "data_binding": {}}], "template": "string", "collection_type": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"agent_strategy": "string", "agent_flow_id": "string", "geo_ai_summary": "string", "geo_ai_crawlers": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "title": "string", "description": "string", "blocks": [{"id": "string", "type": "hero", "data": {}, "component_slug": "string", "component_version": "string", "props": {}, "layout": "string", "data_binding": {}}], "template": "string", "collection_type": "string"}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/content/pages/{page_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/content/pages/{page_id}

Delete Page

Archive a page (soft delete). Phase 11+12 dry_run/confirm_token gated. P4 lock-aware.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the delete.
forcequerybooleanfalseP4: bypass page lock (super_admin / brand_admin only).
Try it
Query

Examples

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

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/{page_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/content/pages/{page_id}", 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/content/pages/{page_id}/preview

Page Preview

Issue a short-lived iframe preview URL for the in-flight blocks the editor is currently showing. The URL is loaded by the Page Editor iframe; the Liquid renderer reads the token via __spideriq_preview_token query param and substitutes page.blocks with the supplied draft before rendering.

Tokens expire in 15 minutes — the editor will refetch on focus/edit. Lock 1 ↔ Lock 5: tenancy is enforced by validating the page belongs to the caller's resolved client_id; the snapshot stored in Redis carries the resolved client_id, not anything from the URL.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/preview' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "blocks": [
    {
      "type": "string",
      "data": {}
    }
  ],
  "draft_mode": true
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/preview",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"blocks": [{"type": "string", "data": {}}], "draft_mode": true},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/preview", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"blocks": [{"type": "string", "data": {}}], "draft_mode": true})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"blocks": [{"type": "string", "data": {}}], "draft_mode": true}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/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/content/posts/{post_id}/preview

Post Preview

Issue a short-lived, token-gated preview URL for a DRAFT blog post.

Draft posts 404 at /blog/<slug> on the live site (the public API serves published-only), so a human reviewer can't see one before publish. This mints an opaque 15-minute token bound to (client_id, slug); the returned URL proxies the tenant's deployed Liquid renderer at /blog/<slug> with the token, and the renderer substitutes the fresh draft post (noindex, no-store).

Lock 1 ↔ Lock 5: the post is fetched scoped to the caller's resolved client_id; the Redis snapshot stores that client_id, never anything from the URL. Works for any status (draft/published) — most useful for drafts.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/preview' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/preview",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/preview", {
  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/content/posts/{post_id}/preview", 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/content/pages/{page_id}/publish

Publish Page

Publish a page (creates version snapshot). Phase 11+12 dry_run/confirm_token gated. P4 lock-aware.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the publish.
forcequerybooleanfalseP4: bypass page lock (super_admin / brand_admin only).
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/publish' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/publish",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/publish", {
  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/content/pages/{page_id}/publish", 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/content/pages/{page_id}/duplicate

Duplicate Page

Duplicate a page. New row: status='draft', fresh UUIDs on every block, auto-generated slug (or caller-provided new_slug). The copy is always owned by the caller's client — no cross-tenant duplication via this endpoint.

Enables the Apr-24 catalog-triage follow-on work (template gallery, section library, import adapters all build on this primitive).

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/duplicate' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/duplicate",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/duplicate", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/duplicate", 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
POST/api/v1/dashboard/content/pages/{page_id}/blocks/{block_id}/duplicate

Duplicate Page Block

Insert a deep copy of one block into the same page. Fresh UUID on the new block; same data/props/component_slug as the source.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
block_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/blocks/{block_id}/duplicate' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "position": "after"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/blocks/{block_id}/duplicate",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"position": "after"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/blocks/{block_id}/duplicate", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"position": "after"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"position": "after"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/blocks/{block_id}/duplicate", 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/content/pages/{page_id}/insert-section

Insert Section Into Page Endpoint

Insert a marketplace section into an existing page (Phase C).

Request body matches InsertSectionRequest: { component_slug, component_version?, props?, position?, anchor_block_id?, data_binding?, layout_id? }

Phase 11+12 gated. dry_run=true returns the preview envelope; confirm_token consumes it and performs the mutation.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the insertion and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and apply the insertion.
forcequerybooleanfalseP4: bypass page lock (super_admin / brand_admin only).
audit_levelquerystringfalseP5: include an _audit block on the success response. Default 'all' for mutations so agents see every finding immediately. 'off' is available for tight-loop scripts that bulk-insert and audit later.
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/insert-section' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/insert-section",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/insert-section", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/insert-section", 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/content/pages/{page_id}/unpublish

Unpublish Page

Revert page to draft status. Phase 11+12 dry_run/confirm_token gated. P4 lock-aware.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the unpublish.
forcequerybooleanfalseP4: bypass page lock (super_admin / brand_admin only).
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/unpublish' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/unpublish",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/unpublish", {
  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/content/pages/{page_id}/unpublish", 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/content/pages/{page_id}/versions

Get Page Versions

List version snapshots for a page (newest first).

P4: each row reports block_count + blocks_size so the editor can summarise without round-tripping the full snapshot. Use GET /pages/{id}/versions/{version_number} to fetch a single snapshot in full (with blocks).

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/versions' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/versions",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/versions", {
  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/content/pages/{page_id}/versions", 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/content/pages/{page_id}/versions/{version_number}

Get Page Version

Fetch a single page version snapshot in full (includes blocks).

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
version_numberpathintegertrue
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/versions/{version_number}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/versions/{version_number}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/versions/{version_number}", {
  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/content/pages/{page_id}/versions/{version_number}", 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/content/pages/{page_id}/lock

Lock Page Endpoint

Lock a page against further mutations.

P4 — agent-surface hardening. Idempotent: re-locking refreshes the reason/timestamp. Any role with content-scoped access can lock; unlock authorisation is more restrictive (lock-holder OR force=true with super_admin / brand_admin).

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/lock' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/lock",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/lock", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/lock", 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
423Page already locked
422Validation Error
POST/api/v1/dashboard/content/pages/{page_id}/unlock

Unlock Page Endpoint

Unlock a page.

Authorisation:

  • Anyone whose user_id matches locked_by_actor_id can unlock.
  • super_admin / brand_admin can unlock with ?force=true.
  • Otherwise: 403 (force gate) or "Page not found / not authorised" (200 with the unchanged row would be a misleading response — we 404 so the caller distinguishes "the page doesn't exist" from "it's locked by someone else", since the latter is itself the answer to the permission question).

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
forcequerybooleanfalsesuper_admin / brand_admin override — unlock regardless of who locked.
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/unlock' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/unlock",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/unlock", {
  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/content/pages/{page_id}/unlock", 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/content/pages/{page_id}/restore

Restore Page Version Endpoint

Restore a page to a historical version snapshot.

Phase 11+12 gated. dry_run=true returns a preview envelope with the snapshot summary. The page lock is enforced — call with force=true (super_admin / brand_admin) to override.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
version_numberqueryintegertrueWhich version to restore (1-indexed).
dry_runquerybooleanfalsePhase 11+12: preview the restore + receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the restore.
forcequerybooleanfalseP4: bypass page lock (super_admin / brand_admin only).
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/restore' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/restore",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/restore", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/restore", 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/content/pages/{page_id}/export

Export Page

Self-contained page export with audit (P2 — agent-surface hardening).

Returns the page row + every component referenced by page.blocks (full body inlined: html_template / js / css / props_schema / dependencies / agent_meta / kind / layouts) + site-level settings + domains + a PageAuditor walk over the same data.

Three formats:

  • format=json (default) — flat JSON envelope
  • format=md — human-readable Markdown (text/markdown)
  • format=archive — ZIP byte stream (application/zip), VSCode-extension-compatible

The page must belong to the caller's client_id (Lock 5 — same multi-tenant scope as GET /pages/{id}).

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
formatqueryanyfalsejson (default) and llm return the flat JSON envelope; md returns human-readable Markdown; archive returns a ZIP whose layout matches the VSCode extension's local format.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/export' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/export",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/export", {
  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/content/pages/{page_id}/export", 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/content/posts

List Posts

List all blog posts (including drafts). Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

NameInTypeRequiredDescription
pagequeryintegerfalse
page_sizequeryintegerfalse
statusqueryanyfalse
tagqueryanyfalse
categoryqueryanyfalseFilter by category id
author_idqueryanyfalseFilter by author (byline) id
created_byqueryanyfalseFilter by record creator / agent id
created_afterqueryanyfalseOnly posts published-or-created on/after this ISO timestamp (time-window filter)
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/posts",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/posts", {
  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/content/posts", 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/content/posts

Create Post

Create a new blog post. Phase 11+12 dry_run/confirm_token gated.

Unknown fields in the request body are silently dropped by Pydantic (extra='ignore' default) but surfaced in warnings[] on the response with a "Did you mean X?" hint. Catches the common cover_image vs cover_image_url / category_id vs category_ids / featured vs is_featured confusions that AI agents fall into.

Parameters

NameInTypeRequiredDescription
dry_runquerybooleanfalsePhase 11+12: preview the create and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the create.
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/posts' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "slug": "string",
  "title": "string",
  "excerpt": "string",
  "agent_strategy": "string",
  "agent_flow_id": "string",
  "body": {},
  "cover_image_url": "string",
  "author_name": "string",
  "author_id": "00000000-0000-0000-0000-000000000000",
  "tags": [
    "string"
  ],
  "tag_ids": [
    "00000000-0000-0000-0000-000000000000"
  ],
  "category_ids": [
    "00000000-0000-0000-0000-000000000000"
  ],
  "is_featured": false,
  "featured_image_alt": "string",
  "tldr_summary": "string",
  "related_post_ids": [
    "00000000-0000-0000-0000-000000000000"
  ],
  "seo_title": "string",
  "seo_description": "string",
  "og_image_url": "string",
  "custom_fields": {}
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/posts",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"slug": "string", "title": "string", "excerpt": "string", "agent_strategy": "string", "agent_flow_id": "string", "body": {}, "cover_image_url": "string", "author_name": "string", "author_id": "00000000-0000-0000-0000-000000000000", "tags": ["string"], "tag_ids": ["00000000-0000-0000-0000-000000000000"], "category_ids": ["00000000-0000-0000-0000-000000000000"], "is_featured": false, "featured_image_alt": "string", "tldr_summary": "string", "related_post_ids": ["00000000-0000-0000-0000-000000000000"], "seo_title": "string", "seo_description": "string", "og_image_url": "string", "custom_fields": {}},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/posts", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"slug": "string", "title": "string", "excerpt": "string", "agent_strategy": "string", "agent_flow_id": "string", "body": {}, "cover_image_url": "string", "author_name": "string", "author_id": "00000000-0000-0000-0000-000000000000", "tags": ["string"], "tag_ids": ["00000000-0000-0000-0000-000000000000"], "category_ids": ["00000000-0000-0000-0000-000000000000"], "is_featured": false, "featured_image_alt": "string", "tldr_summary": "string", "related_post_ids": ["00000000-0000-0000-0000-000000000000"], "seo_title": "string", "seo_description": "string", "og_image_url": "string", "custom_fields": {}})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"slug": "string", "title": "string", "excerpt": "string", "agent_strategy": "string", "agent_flow_id": "string", "body": {}, "cover_image_url": "string", "author_name": "string", "author_id": "00000000-0000-0000-0000-000000000000", "tags": ["string"], "tag_ids": ["00000000-0000-0000-0000-000000000000"], "category_ids": ["00000000-0000-0000-0000-000000000000"], "is_featured": false, "featured_image_alt": "string", "tldr_summary": "string", "related_post_ids": ["00000000-0000-0000-0000-000000000000"], "seo_title": "string", "seo_description": "string", "og_image_url": "string", "custom_fields": {}}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/posts", 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/content/posts/{post_id}

Get Post

Get a post by ID. Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/posts/{post_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/content/posts/{post_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/content/posts/{post_id}

Update Post

Update a blog post. Phase 11+12 dry_run/confirm_token gated.

Unknown fields in the request body are silently dropped by Pydantic but surfaced in warnings[] on the response with a "Did you mean X?" hint. Catches the common cover_image vs cover_image_url / category_id vs category_ids / featured vs is_featured confusions.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the update and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the update.
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "agent_strategy": "string",
  "agent_flow_id": "string",
  "title": "string",
  "slug": "string",
  "excerpt": "string",
  "body": {},
  "cover_image_url": "string",
  "author_name": "string",
  "author_id": "00000000-0000-0000-0000-000000000000",
  "tags": [
    "string"
  ],
  "tag_ids": [
    "00000000-0000-0000-0000-000000000000"
  ],
  "category_ids": [
    "00000000-0000-0000-0000-000000000000"
  ],
  "is_featured": true,
  "featured_image_alt": "string",
  "tldr_summary": "string",
  "related_post_ids": [
    "00000000-0000-0000-0000-000000000000"
  ],
  "seo_title": "string",
  "seo_description": "string",
  "og_image_url": "string",
  "custom_fields": {}
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"agent_strategy": "string", "agent_flow_id": "string", "title": "string", "slug": "string", "excerpt": "string", "body": {}, "cover_image_url": "string", "author_name": "string", "author_id": "00000000-0000-0000-0000-000000000000", "tags": ["string"], "tag_ids": ["00000000-0000-0000-0000-000000000000"], "category_ids": ["00000000-0000-0000-0000-000000000000"], "is_featured": true, "featured_image_alt": "string", "tldr_summary": "string", "related_post_ids": ["00000000-0000-0000-0000-000000000000"], "seo_title": "string", "seo_description": "string", "og_image_url": "string", "custom_fields": {}},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"agent_strategy": "string", "agent_flow_id": "string", "title": "string", "slug": "string", "excerpt": "string", "body": {}, "cover_image_url": "string", "author_name": "string", "author_id": "00000000-0000-0000-0000-000000000000", "tags": ["string"], "tag_ids": ["00000000-0000-0000-0000-000000000000"], "category_ids": ["00000000-0000-0000-0000-000000000000"], "is_featured": true, "featured_image_alt": "string", "tldr_summary": "string", "related_post_ids": ["00000000-0000-0000-0000-000000000000"], "seo_title": "string", "seo_description": "string", "og_image_url": "string", "custom_fields": {}})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"agent_strategy": "string", "agent_flow_id": "string", "title": "string", "slug": "string", "excerpt": "string", "body": {}, "cover_image_url": "string", "author_name": "string", "author_id": "00000000-0000-0000-0000-000000000000", "tags": ["string"], "tag_ids": ["00000000-0000-0000-0000-000000000000"], "category_ids": ["00000000-0000-0000-0000-000000000000"], "is_featured": true, "featured_image_alt": "string", "tldr_summary": "string", "related_post_ids": ["00000000-0000-0000-0000-000000000000"], "seo_title": "string", "seo_description": "string", "og_image_url": "string", "custom_fields": {}}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/content/posts/{post_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/content/posts/{post_id}

Delete Post

Delete a blog post. Phase 11+12 dry_run/confirm_token gated.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the delete and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the delete.
Try it
Query

Examples

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

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/posts/{post_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/content/posts/{post_id}", 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/content/posts/{post_id}/publish

Publish Post

Publish a blog post.

Body is OPTIONAL. published_at backdates the publication (archive import); for a FUTURE go-live use POST /posts/{id}/schedule instead.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/publish' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "published_at": "2026-01-01T00:00:00Z"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/publish",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"published_at": "2026-01-01T00:00:00Z"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/publish", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"published_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(`{"published_at": "2026-01-01T00:00:00Z"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/publish", 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/content/posts/{post_id}/unpublish

Unpublish Post

Unpublish a blog post (set to draft).

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/unpublish' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/unpublish",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/unpublish", {
  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/content/posts/{post_id}/unpublish", 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/content/posts/{post_id}/schedule

Schedule Post

Schedule a post to auto-publish at a future time (status='scheduled').

The scheduler sidecar flips it to 'published' once the time arrives. Public surfaces gate on status='published', so a scheduled post stays private until then. A non-future time is rejected — use /publish for immediate publish.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/schedule' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "published_at": "2026-01-01T00:00:00Z"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/schedule",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"published_at": "2026-01-01T00:00:00Z"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/schedule", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"published_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(`{"published_at": "2026-01-01T00:00:00Z"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/schedule", 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/content/posts/{post_id}/unschedule

Unschedule Post

Cancel a scheduled publish — revert the post to draft.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/unschedule' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/unschedule",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/unschedule", {
  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/content/posts/{post_id}/unschedule", 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/content/posts/{post_id}/duplicate

Duplicate Post

Duplicate a blog post. Returns the new draft with a fresh slug + UUID.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/duplicate' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/duplicate",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/duplicate", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/duplicate", 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
POST/api/v1/dashboard/content/posts/{post_id}/status

Update Post Status

Update post status (draft, pending_review, published, archived).

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/status' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "status": "draft"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/status",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"status": "draft"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/status", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"status": "draft"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"status": "draft"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/status", 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
PUT/api/v1/dashboard/content/posts/{post_id}/related

Update Post Related

Set related posts for a post.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X PUT 'https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/related' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '[
  "string"
]'
Python
import httpx

resp = httpx.put(
    "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/related",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json=["string"],
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/related", {
  method: "PUT",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify(["string"])
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`["string"]`)
	req, _ := http.NewRequest("PUT", "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/related", 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/content/authors

List Authors

List all authors. Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

NameInTypeRequiredDescription
pagequeryintegerfalse
page_sizequeryintegerfalse
agent_typequeryanyfalse
is_activequeryanyfalse
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/authors",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/authors", {
  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/content/authors", 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/content/authors

Create Author

Create a new author.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/authors' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "full_name": "string",
  "slug": "string",
  "avatar_url": "string",
  "bio": "string",
  "email": "string",
  "role": "author",
  "agent_type": "human",
  "country": "string",
  "city": "string"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/authors",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"full_name": "string", "slug": "string", "avatar_url": "string", "bio": "string", "email": "string", "role": "author", "agent_type": "human", "country": "string", "city": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/authors", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"full_name": "string", "slug": "string", "avatar_url": "string", "bio": "string", "email": "string", "role": "author", "agent_type": "human", "country": "string", "city": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"full_name": "string", "slug": "string", "avatar_url": "string", "bio": "string", "email": "string", "role": "author", "agent_type": "human", "country": "string", "city": "string"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/authors", 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/content/authors/{author_id}

Get Author

Get an author by ID. Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

NameInTypeRequiredDescription
author_idpathstringtrue
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/authors/{author_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/authors/{author_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/content/authors/{author_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/content/authors/{author_id}

Update Author

Update an author.

Parameters

NameInTypeRequiredDescription
author_idpathstringtrue
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/content/authors/{author_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "full_name": "string",
  "slug": "string",
  "avatar_url": "string",
  "bio": "string",
  "email": "string",
  "role": "author",
  "agent_type": "human",
  "country": "string",
  "city": "string",
  "is_active": true
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/content/authors/{author_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"full_name": "string", "slug": "string", "avatar_url": "string", "bio": "string", "email": "string", "role": "author", "agent_type": "human", "country": "string", "city": "string", "is_active": true},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/authors/{author_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"full_name": "string", "slug": "string", "avatar_url": "string", "bio": "string", "email": "string", "role": "author", "agent_type": "human", "country": "string", "city": "string", "is_active": true})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"full_name": "string", "slug": "string", "avatar_url": "string", "bio": "string", "email": "string", "role": "author", "agent_type": "human", "country": "string", "city": "string", "is_active": true}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/content/authors/{author_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/content/authors/{author_id}

Delete Author

Deactivate an author (soft-delete).

Parameters

NameInTypeRequiredDescription
author_idpathstringtrue
Try it
Query

Examples

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

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/content/authors/{author_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/authors/{author_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/content/authors/{author_id}", 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/content/tags

List Tags

List all tags. Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

NameInTypeRequiredDescription
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/tags",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/tags", {
  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/content/tags", 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/content/tags

Create Tag

Create a new tag.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/tags' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "slug": "string",
  "description": "string"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/tags",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "slug": "string", "description": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/tags", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "slug": "string", "description": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "slug": "string", "description": "string"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/tags", 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
PATCH/api/v1/dashboard/content/tags/{tag_id}

Update Tag

Update a tag.

Parameters

NameInTypeRequiredDescription
tag_idpathstringtrue
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/content/tags/{tag_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "slug": "string",
  "description": "string"
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/content/tags/{tag_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "slug": "string", "description": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/tags/{tag_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "slug": "string", "description": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "slug": "string", "description": "string"}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/content/tags/{tag_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/content/tags/{tag_id}

Delete Tag

Delete a tag.

Parameters

NameInTypeRequiredDescription
tag_idpathstringtrue
Try it
Query

Examples

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

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/content/tags/{tag_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/tags/{tag_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/content/tags/{tag_id}", 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/content/categories

List Categories

List blog categories. Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

NameInTypeRequiredDescription
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/categories",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/categories", {
  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/content/categories", 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/content/categories

Create Category

Create a new category.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/categories' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "slug": "string",
  "description": "string",
  "parent_id": "00000000-0000-0000-0000-000000000000",
  "sort_order": 0
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/categories",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "slug": "string", "description": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/categories", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "slug": "string", "description": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "slug": "string", "description": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/categories", 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
PATCH/api/v1/dashboard/content/categories/{category_id}

Update Category

Update a category.

Parameters

NameInTypeRequiredDescription
category_idpathstringtrue
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/content/categories/{category_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "slug": "string",
  "description": "string",
  "parent_id": "00000000-0000-0000-0000-000000000000",
  "sort_order": 0
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/content/categories/{category_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "slug": "string", "description": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/categories/{category_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "slug": "string", "description": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "slug": "string", "description": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/content/categories/{category_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/content/categories/{category_id}

Delete Category

Delete a category.

Parameters

NameInTypeRequiredDescription
category_idpathstringtrue
Try it
Query

Examples

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

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/content/categories/{category_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/categories/{category_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/content/categories/{category_id}", 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/content/docs/tree

Get Docs Tree

Get full docs tree (including drafts).

Docs Platform v2 · 3.4 — ?version= scopes the editor tree to one docs version (omit → default). Response carries all versions (every status, for management) + the resolved current_version.

Parameters

NameInTypeRequiredDescription
versionqueryanyfalse
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/docs/tree",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/tree", {
  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/content/docs/tree", 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/content/docs

List Docs

Flat list of docs (metadata only, no body) — complements GET /docs/tree.

Agents use this to discover a doc's UUID by title/status before fetching or mutating it via GET /docs/{doc_id}.

Parameters

NameInTypeRequiredDescription
statusqueryanyfalseFilter by status (draft / published / archived).
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/docs",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs", {
  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/content/docs", 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/content/docs

Create Doc

Create a documentation page.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/docs' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "agent_strategy": "string",
  "agent_flow_id": "string",
  "seo_title": "string",
  "seo_description": "string",
  "og_title": "string",
  "og_description": "string",
  "og_image_url": "string",
  "twitter_card": "string",
  "twitter_image_url": "string",
  "canonical_url": "string",
  "robots": "string",
  "keywords": "string",
  "json_ld": {},
  "parent_id": "00000000-0000-0000-0000-000000000000",
  "slug": "string",
  "title": "string",
  "body": {},
  "is_section": false,
  "sort_order": 0,
  "version": "default"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/docs",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"agent_strategy": "string", "agent_flow_id": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "parent_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "body": {}, "is_section": false, "sort_order": 0, "version": "default"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"agent_strategy": "string", "agent_flow_id": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "parent_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "body": {}, "is_section": false, "sort_order": 0, "version": "default"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"agent_strategy": "string", "agent_flow_id": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "parent_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "body": {}, "is_section": false, "sort_order": 0, "version": "default"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/docs", 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/content/docs/versions

List Doc Versions

List the tenant's docs versions (all statuses, for management).

Try it

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/docs/versions",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/versions", {
  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/content/docs/versions", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
POST/api/v1/dashboard/content/docs/versions

Create Doc Version

Register a new docs version label. is_default demotes the prior default.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/docs/versions' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "label": "string",
  "title": "string",
  "is_default": false,
  "sort_order": 0,
  "status": "published"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/docs/versions",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"label": "string", "title": "string", "is_default": false, "sort_order": 0, "status": "published"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/versions", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"label": "string", "title": "string", "is_default": false, "sort_order": 0, "status": "published"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"label": "string", "title": "string", "is_default": false, "sort_order": 0, "status": "published"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/docs/versions", 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
PATCH/api/v1/dashboard/content/docs/versions/{version_id}

Update Doc Version

Update a docs version (title / order / status / default flag).

Parameters

NameInTypeRequiredDescription
version_idpathstringtrue
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/content/docs/versions/{version_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "title": "string",
  "is_default": true,
  "sort_order": 0,
  "status": "string"
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/content/docs/versions/{version_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"title": "string", "is_default": true, "sort_order": 0, "status": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/versions/{version_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"title": "string", "is_default": true, "sort_order": 0, "status": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"title": "string", "is_default": true, "sort_order": 0, "status": "string"}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/content/docs/versions/{version_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/content/docs/versions/{version_id}

Delete Doc Version

Delete a docs version. Refuses the default version or one still in use.

Parameters

NameInTypeRequiredDescription
version_idpathstringtrue
Try it
Query

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/content/docs/versions/{version_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/content/docs/versions/{version_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/versions/{version_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/content/docs/versions/{version_id}", 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/content/docs/analytics

Get Docs Analytics

Server-side docs analytics overview (views / searches / asks) for the tenant over the last days. Degrades to an empty rollup, never 500s.

Parameters

NameInTypeRequiredDescription
daysqueryintegerfalse
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/docs/analytics",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/analytics", {
  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/content/docs/analytics", 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/content/docs/{doc_id}

Get Doc

Get a doc by ID (drafts included).

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/{doc_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/content/docs/{doc_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/content/docs/{doc_id}

Update Doc

Update a doc (title, body, SEO, hierarchy). Phase 11+12 dry_run/confirm_token gated.

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the update and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the update.
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "agent_strategy": "string",
  "agent_flow_id": "string",
  "seo_title": "string",
  "seo_description": "string",
  "og_title": "string",
  "og_description": "string",
  "og_image_url": "string",
  "twitter_card": "string",
  "twitter_image_url": "string",
  "canonical_url": "string",
  "robots": "string",
  "keywords": "string",
  "json_ld": {},
  "parent_id": "00000000-0000-0000-0000-000000000000",
  "title": "string",
  "body": {},
  "is_section": true,
  "sort_order": 0
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"agent_strategy": "string", "agent_flow_id": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "parent_id": "00000000-0000-0000-0000-000000000000", "title": "string", "body": {}, "is_section": true, "sort_order": 0},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"agent_strategy": "string", "agent_flow_id": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "parent_id": "00000000-0000-0000-0000-000000000000", "title": "string", "body": {}, "is_section": true, "sort_order": 0})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"agent_strategy": "string", "agent_flow_id": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "parent_id": "00000000-0000-0000-0000-000000000000", "title": "string", "body": {}, "is_section": true, "sort_order": 0}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/content/docs/{doc_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/content/docs/{doc_id}

Delete Doc

Archive a doc (soft delete). Phase 11+12 dry_run/confirm_token gated.

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the delete.
Try it
Query

Examples

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

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/{doc_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/content/docs/{doc_id}", 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/content/docs/{doc_id}/duplicate

Duplicate Doc

Duplicate a doc page. Copy lives as a sibling of the original under the same parent_id with a fresh slug. Status: draft.

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/duplicate' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/duplicate",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/duplicate", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/duplicate", 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
POST/api/v1/dashboard/content/docs/{doc_id}/publish

Publish Doc

Publish a draft doc. Phase 11+12 dry_run/confirm_token gated.

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the publish.
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/publish' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/publish",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/publish", {
  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/content/docs/{doc_id}/publish", 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/content/docs/{doc_id}/unpublish

Unpublish Doc

Revert a doc to draft status. Phase 11+12 dry_run/confirm_token gated.

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the unpublish.
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/unpublish' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/unpublish",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/unpublish", {
  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/content/docs/{doc_id}/unpublish", 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/content/docs/{doc_id}/export

Export Doc

Self-contained doc export. Returns the doc row + site settings + domains.

Docs are prose-first, so there are no component bodies to inline (unlike page export). The doc must belong to the caller's client_id.

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
formatqueryanyfalseResponse format. json (default) and llm return JSON; md returns text/markdown. This route has no YAML renderer, so yaml is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/export' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/export",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/export", {
  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/content/docs/{doc_id}/export", 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/content/docs/import

Import Doc Markdown

Import a doc from a Markdown body. Create a new doc (omit doc_id, provide slug + title) or replace an existing doc's body (set doc_id). :::component{...} directives become embedded component nodes.

Create delegates to create_doc (ungated); update delegates to the Phase 11+12 dry_run/confirm_token-gated update_doc.

Parameters

NameInTypeRequiredDescription
dry_runquerybooleanfalsePhase 11+12 (update path): preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12 (update path): consume a prior preview token and perform the update.
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/docs/import' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "seo_title": "string",
  "seo_description": "string",
  "og_title": "string",
  "og_description": "string",
  "og_image_url": "string",
  "twitter_card": "string",
  "twitter_image_url": "string",
  "canonical_url": "string",
  "robots": "string",
  "keywords": "string",
  "json_ld": {},
  "markdown": "string",
  "doc_id": "00000000-0000-0000-0000-000000000000",
  "slug": "string",
  "title": "string",
  "parent_id": "00000000-0000-0000-0000-000000000000",
  "is_section": true,
  "sort_order": 0
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/docs/import",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "markdown": "string", "doc_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "is_section": true, "sort_order": 0},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/import", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "markdown": "string", "doc_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "is_section": true, "sort_order": 0})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "markdown": "string", "doc_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "is_section": true, "sort_order": 0}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/docs/import", 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/content/docs/import-openapi

Import Openapi

Import an OpenAPI/Swagger spec into the docs tree. dry_run=true returns the planned section + pages without writing (powers the wizard preview); otherwise the reference is generated idempotently and (if publish) published.

Errors map to 422 (bad/oversized/unfetchable spec — message is client-safe) or 500 (logged, generic) — never leak the spec URL or upstream detail.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/docs/import-openapi' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "source_url": "string",
  "spec_content": "string",
  "spec_format": "auto",
  "section": "api-reference",
  "publish": false,
  "dry_run": false
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/docs/import-openapi",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"source_url": "string", "spec_content": "string", "spec_format": "auto", "section": "api-reference", "publish": false, "dry_run": false},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/import-openapi", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"source_url": "string", "spec_content": "string", "spec_format": "auto", "section": "api-reference", "publish": false, "dry_run": false})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"source_url": "string", "spec_content": "string", "spec_format": "auto", "section": "api-reference", "publish": false, "dry_run": false}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/docs/import-openapi", 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/content/docs/{doc_id}/markdown

Export Doc Markdown

Export a doc's body as pure Markdown (round-trips with POST /docs/import).

:::component{...} directives are preserved (render_tiptap_markdown emits them via serialize_component_node). The title is prepended as an H1. Distinct from /docs/{id}/export?format=md, which wraps the same body in a JSON envelope.

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/markdown' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/markdown",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/markdown", {
  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/content/docs/{doc_id}/markdown", 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/content/pages/import

Import Page Markdown

Import a page from a Markdown body — the markdown→page converter. Create a new page (omit page_id, provide slug + title) or replace an existing page's blocks (set page_id). Prose runs become rich_text blocks; :::component{...} directives become component blocks.

Delegates to the Phase 11+12 dry_run/confirm_token-gated create_page / update_page (the converter handler only does the markdown→blocks mapping).

Parameters

NameInTypeRequiredDescription
dry_runquerybooleanfalsePhase 11+12: preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the create/update.
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/pages/import' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "seo_title": "string",
  "seo_description": "string",
  "og_title": "string",
  "og_description": "string",
  "og_image_url": "string",
  "twitter_card": "string",
  "twitter_image_url": "string",
  "canonical_url": "string",
  "robots": "string",
  "keywords": "string",
  "json_ld": {},
  "markdown": "string",
  "page_id": "00000000-0000-0000-0000-000000000000",
  "slug": "string",
  "title": "string",
  "template": "string",
  "parent_id": "00000000-0000-0000-0000-000000000000",
  "sort_order": 0
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/pages/import",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "markdown": "string", "page_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "template": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/import", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "markdown": "string", "page_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "template": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "markdown": "string", "page_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "template": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/pages/import", 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/content/pages/{page_id}/markdown

Export Page Markdown

Export a page's blocks as pure Markdown (round-trips with POST /pages/import).

Component blocks serialize to :::component{...} directives (the converter contract — render_page_markdown(serialize_components=True)). This differs from /pages/{id}/export?format=md, which renders each component as a labelled human-readable section inside a JSON envelope (not round-trippable).

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/markdown' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/markdown",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/markdown", {
  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/content/pages/{page_id}/markdown", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
422Validation Error
PUT/api/v1/dashboard/content/docs/reorder

Reorder Docs

Reorder documentation tree.

Try it

Examples

cURL
curl -X PUT 'https://spideriq.ai/api/v1/dashboard/content/docs/reorder' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "items": [
    {}
  ]
}'
Python
import httpx

resp = httpx.put(
    "https://spideriq.ai/api/v1/dashboard/content/docs/reorder",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"items": [{}]},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/reorder", {
  method: "PUT",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"items": [{}]})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"items": [{}]}`)
	req, _ := http.NewRequest("PUT", "https://spideriq.ai/api/v1/dashboard/content/docs/reorder", 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/content/navigation/{location}

Get Navigation

Get navigation menu.

D4 — the editor reads the RAW menu (expand=False, the service default). A folder-bound item must round-trip as its BINDING; expanding here would make the next save bake a frozen snapshot of the page tree into the JSONB.

Parameters

NameInTypeRequiredDescription
locationpathstringtrue
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/navigation/{location}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/navigation/{location}", {
  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/content/navigation/{location}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
422Validation Error
PUT/api/v1/dashboard/content/navigation/{location}

Update Navigation

Update navigation menu.

Parameters

NameInTypeRequiredDescription
locationpathstringtrue
Try it
Query

Examples

cURL
curl -X PUT 'https://spideriq.ai/api/v1/dashboard/content/navigation/{location}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "items": [
    {
      "label": "string",
      "url": "string",
      "icon": "string",
      "children": [],
      "is_external": false,
      "badge": "string",
      "source": {
        "kind": "site",
        "folder_id": {},
        "depth": 2
      }
    }
  ]
}'
Python
import httpx

resp = httpx.put(
    "https://spideriq.ai/api/v1/dashboard/content/navigation/{location}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"items": [{"label": "string", "url": "string", "icon": "string", "children": [], "is_external": false, "badge": "string", "source": {"kind": "site", "folder_id": {}, "depth": 2}}]},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/navigation/{location}", {
  method: "PUT",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"items": [{"label": "string", "url": "string", "icon": "string", "children": [], "is_external": false, "badge": "string", "source": {"kind": "site", "folder_id": {}, "depth": 2}}]})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"items": [{"label": "string", "url": "string", "icon": "string", "children": [], "is_external": false, "badge": "string", "source": {"kind": "site", "folder_id": {}, "depth": 2}}]}`)
	req, _ := http.NewRequest("PUT", "https://spideriq.ai/api/v1/dashboard/content/navigation/{location}", 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/content/directory/categories

Dash List Directory Categories

List all directory categories for this client (includes drafts/empty ones).

Parameters

NameInTypeRequiredDescription
pagequeryintegerfalse
page_sizequeryintegerfalse
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/directory/categories",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/directory/categories", {
  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/content/directory/categories", 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/content/directory/categories

Dash Create Directory Category

Create a directory category.

Body: {name, slug?, description?, icon?, seo_title_template?, seo_description_template?, template?, data_source?, sort_order?}

seo_*_template strings accept {category}, {city}, {listing} placeholders — rendered server-side on the public read endpoints.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/directory/categories' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

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

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/directory/categories", 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/content/directory/categories/{category_slug}

Dash Get Directory Category

Parameters

NameInTypeRequiredDescription
category_slugpathstringtrue
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}", {
  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/content/directory/categories/{category_slug}", 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/content/directory/categories/{category_slug}

Dash Update Directory Category

Parameters

NameInTypeRequiredDescription
category_slugpathstringtrue
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}", 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/content/directory/categories/{category_slug}

Dash Delete Directory Category

Delete a category (cascades to its listings).

Parameters

NameInTypeRequiredDescription
category_slugpathstringtrue
Try it
Query

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}", {
  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/content/directory/categories/{category_slug}", 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/content/directory/categories/{category_slug}/listings/bulk

Dash Bulk Upsert Listings

Bulk upsert listings. Body: {listings: [{name, slug?, city, state?, ...}, ...]}.

Upsert semantics: slug unique per category. Missing slug auto-generated from name. Refreshes the materialized view + category counts on success.

Typical use: agent dumps the results of a SpiderMaps campaign into a category via a single call. Supports source_job_id so listings can be traced back to the job that produced them.

Parameters

NameInTypeRequiredDescription
category_slugpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}/listings/bulk' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}/listings/bulk",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}/listings/bulk", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}/listings/bulk", 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/content/directory/listings

Dash List Directory Listings

List listings across categories. Filters: category_slug, city, status.

Parameters

NameInTypeRequiredDescription
category_slugqueryanyfalse
cityqueryanyfalse
statusquerystringfalse
pagequeryintegerfalse
page_sizequeryintegerfalse
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/directory/listings",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/directory/listings", {
  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/content/directory/listings", 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/content/directory/categories/{category_slug}/listings

Dash Upsert Listing

Create or update a single listing in a category. Slug-based upsert.

Parameters

NameInTypeRequiredDescription
category_slugpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}/listings' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}/listings",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}/listings", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}/listings", 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/content/directory/categories/{category_slug}/listings/{listing_slug}

Dash Delete Listing

Parameters

NameInTypeRequiredDescription
category_slugpathstringtrue
listing_slugpathstringtrue
Try it
Query

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}/listings/{listing_slug}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}/listings/{listing_slug}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}/listings/{listing_slug}", {
  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/content/directory/categories/{category_slug}/listings/{listing_slug}", 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/content/directory/categories/{category_slug}/import-from-idap

Dash Import From Idap

Populate a directory category from the tenant's IDAP data (norm_cli_*.businesses).

One call replaces the "run SpiderMaps → transform results → bulk_upsert" loop. The norm_cli_* schema is already the canonical store for every business SpiderIQ has seen for this tenant — this reads directly from it.

Every column the IDAP column manifest declares reaches the listing — typed columns land in typed columns, the rest land in the data jsonb under their frozen public field id.

Body (all optional): {category_filter: "Plumber", country_code: "US", city: "Miami", rating_min: 4.0, limit: 5000, prune: false}

prune: true ARCHIVES (never deletes) listings in this category whose source row no longer matches the filter — that is what makes a re-import honest, since the upsert is keyed on (category, slug) and a business deleted or renamed in IDAP otherwise leaves a stale published listing forever. It is OFF by default, and it refuses to run when the import hit its limit (a truncated result set cannot tell "gone" from "on the next page") — the refusal comes back as prune_skipped_reason.

Returns {upserted, inserted, updated, pruned, failed, source_rows, affected_cities, source_schema, fields_mapped, filter, sync_log_id, ...}.

Parameters

NameInTypeRequiredDescription
category_slugpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}/import-from-idap' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}/import-from-idap",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}/import-from-idap", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/directory/categories/{category_slug}/import-from-idap", 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/content/directory/refresh-stats

Dash Refresh Directory Stats

Manually refresh the city_stats materialized view. Normally auto-refreshed on bulk upsert.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/directory/refresh-stats' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/directory/refresh-stats",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/directory/refresh-stats", {
  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/content/directory/refresh-stats", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
GET/api/v1/dashboard/content/media

List Media

List media files for the current client, newest first.

Filters: folder (exact match), mime_type (prefix match — image/ catches all image MIME types).

Parameters

NameInTypeRequiredDescription
pagequeryintegerfalse
page_sizequeryintegerfalse
folderqueryanyfalse
mime_typequeryanyfalse
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/media",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/media", {
  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/content/media", 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/content/media/upload

Upload Media

Upload an image to Cloudflare R2.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/media/upload' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "file": "string",
  "folder": "/",
  "alt_text": "string"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/media/upload",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"file": "string", "folder": "/", "alt_text": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/media/upload", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"file": "string", "folder": "/", "alt_text": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"file": "string", "folder": "/", "alt_text": "string"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/media/upload", 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
POST/api/v1/dashboard/content/media/upload-from-url

Upload Media From Url

Host a remote image URL on Cloudflare R2 — the agent-callable, JSON-only twin of POST /media/upload.

Agents reaching the content platform via skill_call can't send multipart, and a generated hero image lives at a provider URL (kie.* etc.) that the cover_image_url allowlist rejects. This fetches the URL SSRF-safely and runs the same validate → WebP-transcode → R2 → content_media → catalog pipeline as /media/upload; the returned media.r2_url is on our allowlisted host, so it then passes straight into createPost / content_update_page with no allowlist change.

201 + {success, media, asset}. A bad/unreachable URL or non-image body is a 400; an oversized body (>5 MB) is a 413.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/media/upload-from-url' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "media_url": "string",
  "folder": "/",
  "alt_text": "string"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/media/upload-from-url",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"media_url": "string", "folder": "/", "alt_text": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/media/upload-from-url", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"media_url": "string", "folder": "/", "alt_text": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"media_url": "string", "folder": "/", "alt_text": "string"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/media/upload-from-url", 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
POST/api/v1/dashboard/content/media/upload-batch

Upload Media Batch

Upload one or many files to SpiderMedia (SeaweedFS).

Weight policy — scroll-sequence folders (scroll-sequences/* or is_scroll_sequence=true): 500 KB per-file hard, 20 MB batch total hard, 200 KB / 10 MB soft warnings. Everything else: 20 MB per-file (500 MB for video/*), 500 MB batch total. Hard ceilings return 400 with the offending file(s); soft warnings come back in warnings[] with the upload succeeding.

Returns {uploaded: [...], failed: [...], warnings: [...], totals}.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/media/upload-batch' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "files": [
    "string"
  ],
  "folder": "string",
  "preserve_filename": false,
  "is_scroll_sequence": false
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/media/upload-batch",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"files": ["string"], "folder": "string", "preserve_filename": false, "is_scroll_sequence": false},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/media/upload-batch", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"files": ["string"], "folder": "string", "preserve_filename": false, "is_scroll_sequence": false})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"files": ["string"], "folder": "string", "preserve_filename": false, "is_scroll_sequence": false}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/media/upload-batch", 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
PATCH/api/v1/dashboard/content/media/{media_id}

Update Media

Update a legacy R2 media file's metadata (folder / alt_text / caption).

Targets the content_media table (the dashboard R2 uploader surface), NOT the per-tenant media_assets catalog. True PATCH — only supplied fields change. 200 + the updated row; 404 if no such media for this client.

Parameters

NameInTypeRequiredDescription
media_idpathstringtrue
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/content/media/{media_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "folder": "string",
  "alt_text": "string",
  "caption": "string"
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/content/media/{media_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"folder": "string", "alt_text": "string", "caption": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/media/{media_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"folder": "string", "alt_text": "string", "caption": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"folder": "string", "alt_text": "string", "caption": "string"}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/content/media/{media_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/content/media/{media_id}

Delete Media

Delete a legacy R2 media file (content_media row + best-effort R2 object cleanup). 204 on success, 404 if no such media for this client.

The DB row delete is authoritative; the R2 object removal is best-effort and non-blocking — an orphaned R2 object never fails the request (the row is already gone, so the asset no longer appears in the library).

Parameters

NameInTypeRequiredDescription
media_idpathstringtrue
Try it
Query

Examples

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

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/content/media/{media_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/media/{media_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/content/media/{media_id}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
204Successful Response
422Validation Error
GET/api/v1/dashboard/content/settings

Get Settings

Get content settings.

Try it

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/settings",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/settings", {
  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/content/settings", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
PATCH/api/v1/dashboard/content/settings

Update Settings

Update content settings. Phase 11+12 dry_run/confirm_token gated.

Parameters

NameInTypeRequiredDescription
dry_runquerybooleanfalsePhase 11+12: preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the update.
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/content/settings' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "site_name": "string",
  "site_tagline": "string",
  "favicon_url": "string",
  "primary_color": "string",
  "surface_color": "string",
  "surface_elevated_color": "string",
  "subtle_color": "string",
  "body_text_color": "string",
  "heading_color": "string",
  "logo_dark_url": "string",
  "logo_light_url": "string",
  "copyright_text": "string",
  "social_links": {},
  "google_analytics_id": "string",
  "plausible_domain": "string",
  "default_meta_title": "string",
  "default_meta_description": "string",
  "default_og_image_url": "string",
  "default_seo_title_suffix": "string",
  "default_agent_strategy": "string"
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/content/settings",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"site_name": "string", "site_tagline": "string", "favicon_url": "string", "primary_color": "string", "surface_color": "string", "surface_elevated_color": "string", "subtle_color": "string", "body_text_color": "string", "heading_color": "string", "logo_dark_url": "string", "logo_light_url": "string", "copyright_text": "string", "social_links": {}, "google_analytics_id": "string", "plausible_domain": "string", "default_meta_title": "string", "default_meta_description": "string", "default_og_image_url": "string", "default_seo_title_suffix": "string", "default_agent_strategy": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/settings", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"site_name": "string", "site_tagline": "string", "favicon_url": "string", "primary_color": "string", "surface_color": "string", "surface_elevated_color": "string", "subtle_color": "string", "body_text_color": "string", "heading_color": "string", "logo_dark_url": "string", "logo_light_url": "string", "copyright_text": "string", "social_links": {}, "google_analytics_id": "string", "plausible_domain": "string", "default_meta_title": "string", "default_meta_description": "string", "default_og_image_url": "string", "default_seo_title_suffix": "string", "default_agent_strategy": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"site_name": "string", "site_tagline": "string", "favicon_url": "string", "primary_color": "string", "surface_color": "string", "surface_elevated_color": "string", "subtle_color": "string", "body_text_color": "string", "heading_color": "string", "logo_dark_url": "string", "logo_light_url": "string", "copyright_text": "string", "social_links": {}, "google_analytics_id": "string", "plausible_domain": "string", "default_meta_title": "string", "default_meta_description": "string", "default_og_image_url": "string", "default_seo_title_suffix": "string", "default_agent_strategy": "string"}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/content/settings", 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/content/redirects

List Redirects

List all redirects.

Try it

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/redirects",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/redirects", {
  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/content/redirects", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
POST/api/v1/dashboard/content/redirects

Create Redirect

Create a redirect.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/redirects' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "from_path": "string",
  "to_path": "string",
  "status_code": 301
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/redirects",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"from_path": "string", "to_path": "string", "status_code": 301},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/redirects", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"from_path": "string", "to_path": "string", "status_code": 301})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"from_path": "string", "to_path": "string", "status_code": 301}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/redirects", 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/content/redirects/{redirect_id}

Delete Redirect

Delete a redirect.

Parameters

NameInTypeRequiredDescription
redirect_idpathstringtrue
Try it
Query

Examples

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

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/content/redirects/{redirect_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/redirects/{redirect_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/content/redirects/{redirect_id}", 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/content/domains

List Domains

List all custom domains for this client plus the auto-provisioned platform preview URL when the client has ever deployed.

Try it

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/domains",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/domains", {
  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/content/domains", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
POST/api/v1/dashboard/content/domains

Add Domain

Register a new custom domain.

Drives BOTH Cloudflare onboarding paths and surfaces the outcome of each so the dashboard can render an actionable banner instead of silently masking failures:

  • CF for SaaS custom hostname — for domains whose zone is NOT in our CF account. The client adds a CNAME to the fallback origin and CF handles SSL + dispatch.
  • Worker Route on the domain's own zone — for domains whose zone IS in our CF account (incl. subdomains of zones we own). Without this, KV mappings exist but CF returns 522 because no Worker handles the inbound request.

Each helper detects which path it owns and no-ops on the other (see register_custom_hostname skipping in-account zones, and ensure_worker_route skipping zones in other accounts). Both are called unconditionally; their structured return values populate worker_route_status and custom_hostname_status on the response.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/domains' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "domain": "acme.com"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/domains",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"domain": "acme.com"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/domains", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"domain": "acme.com"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"domain": "acme.com"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/domains", 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/content/domains/subdomain

Add Subdomain

Register a free {label}.sites.spideriq.ai subdomain.

The zero-cost counterpart to add_domain: sites.spideriq.ai is a zone we own with a wildcard Worker Route already configured, so this path makes NO Cloudflare custom-hostname call and needs NO DNS verification — it writes the DOMAIN_MAP KV entry and the dispatch Worker routes the hostname to the client's tenant script. Available on every tier; the free tier's single slot is one of these.

Counts against the same max_domains quota as a custom domain.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/domains/subdomain' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "label": "acme"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/domains/subdomain",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"label": "acme"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/domains/subdomain", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"label": "acme"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"label": "acme"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/domains/subdomain", 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/content/domains/subdomain/availability

Check Subdomain Availability

Check whether a {label}.sites.spideriq.ai subdomain is free.

Powers the live availability check in the dashboard subdomain editor. Returns {available, host, reason}. available=false with a reason when the label is malformed; otherwise reflects global host uniqueness (content_domains.domain is globally unique).

Parameters

NameInTypeRequiredDescription
labelquerystringtrue
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/domains/subdomain/availability",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/domains/subdomain/availability", {
  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/content/domains/subdomain/availability", 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/content/domains/{domain}

Update Domain

Update a domain (SD1): set its start page and/or rename the host.

A rename remaps Cloudflare so the new host serves the same tenant site — the new DOMAIN_MAP KV entry (and, for an out-of-account custom domain, a fresh custom hostname + Worker Route) is created and the old host's mapping is torn down. Subdomains on *.sites.spideriq.ai route via the existing wildcard, so they only need the KV swap. The change goes live on the next deploy.

Parameters

NameInTypeRequiredDescription
domainpathstringtrue
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/content/domains/{domain}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "homepage_slug": "promo",
  "new_domain": "go.acme.com"
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/content/domains/{domain}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"homepage_slug": "promo", "new_domain": "go.acme.com"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/domains/{domain}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"homepage_slug": "promo", "new_domain": "go.acme.com"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"homepage_slug": "promo", "new_domain": "go.acme.com"}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/content/domains/{domain}", 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/content/domains/{domain}

Remove Domain

Remove a custom domain.

Parameters

NameInTypeRequiredDescription
domainpathstringtrue
Try it
Query

Examples

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

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/content/domains/{domain}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/domains/{domain}", {
  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/content/domains/{domain}", 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/content/domains/{domain}/verify

Verify Domain

Verify a domain (checks DNS TXT record).

Surfaces needs_deploy=True when the client has no live deploy yet so the dashboard can prompt "Click to deploy your site" — without that, a freshly verified domain will return CF 522 because the per-client tenant Worker script doesn't exist in the dispatch namespace.

Parameters

NameInTypeRequiredDescription
domainpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/domains/{domain}/verify' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/domains/{domain}/verify",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/domains/{domain}/verify", {
  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/content/domains/{domain}/verify", 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/content/domains/{domain}/recheck

Recheck Domain Ssl

Re-query Cloudflare for this domain's live SSL state and persist it.

The on-demand, customer-triggered counterpart to the background reconciliation poll: powers the dashboard "Re-check" button so a customer who just fixed their DNS doesn't have to wait for the next poll tick. Does exactly ONE Cloudflare custom-hostname read for the one domain (not a fan-out over the whole list — that stays cheap and rate-limit-safe), maps the CF SSL lifecycle onto our ssl_status enum, and returns the refreshed row with the live CF status echoed in custom_hostname_status.

Parameters

NameInTypeRequiredDescription
domainpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/domains/{domain}/recheck' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/domains/{domain}/recheck",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/domains/{domain}/recheck", {
  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/content/domains/{domain}/recheck", 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/content/domains/{domain}/primary

Set Primary Domain

Set a domain as the primary domain for this client.

Parameters

NameInTypeRequiredDescription
domainpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/domains/{domain}/primary' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/domains/{domain}/primary",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/domains/{domain}/primary", {
  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/content/domains/{domain}/primary", 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/content/domains/{domain}/reassign-project

Reassign Domain Project

Move a domain to a different project (website) in the same workspace.

Projects 4a migration helper: every existing domain was backfilled to the workspace DEFAULT project, so a multi-project workspace needs this to assign a domain to its real website (e.g. docs.example.com → the docs project). Workspace-scoped on purpose — the move targets a domain regardless of the currently-selected project, because the point is to move it OUT of its current one. The target project is validated to belong to this workspace.

Parameters

NameInTypeRequiredDescription
domainpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/domains/{domain}/reassign-project' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "project_id": "proj_6c76213060eb"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/domains/{domain}/reassign-project",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"project_id": "proj_6c76213060eb"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/domains/{domain}/reassign-project", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"project_id": "proj_6c76213060eb"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"project_id": "proj_6c76213060eb"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/domains/{domain}/reassign-project", 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/content/pages/{page_id}/reassign-project

Reassign Page Project

Move a page (and its folder subtree) to another project in this workspace.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/reassign-project' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "project_id": "proj_6c76213060eb"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/reassign-project",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"project_id": "proj_6c76213060eb"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/reassign-project", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"project_id": "proj_6c76213060eb"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"project_id": "proj_6c76213060eb"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/pages/{page_id}/reassign-project", 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/content/posts/{post_id}/reassign-project

Reassign Post Project

Move a blog post to another project in this workspace (clears project-scoped categories/tags/relationships; free-text tags + pins ride along).

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/reassign-project' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "project_id": "proj_6c76213060eb"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/reassign-project",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"project_id": "proj_6c76213060eb"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/reassign-project", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"project_id": "proj_6c76213060eb"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"project_id": "proj_6c76213060eb"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/posts/{post_id}/reassign-project", 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/content/docs/{doc_id}/reassign-project

Reassign Doc Project

Move a doc (and its subtree) to another project in this workspace.

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/reassign-project' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "project_id": "proj_6c76213060eb"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/reassign-project",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"project_id": "proj_6c76213060eb"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/reassign-project", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"project_id": "proj_6c76213060eb"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"project_id": "proj_6c76213060eb"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/docs/{doc_id}/reassign-project", 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/content/changelog/{entry_id}/reassign-project

Reassign Changelog Project

Move a changelog entry to another project in this workspace.

Parameters

NameInTypeRequiredDescription
entry_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_id}/reassign-project' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "project_id": "proj_6c76213060eb"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_id}/reassign-project",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"project_id": "proj_6c76213060eb"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_id}/reassign-project", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"project_id": "proj_6c76213060eb"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"project_id": "proj_6c76213060eb"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_id}/reassign-project", 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/content/deploy

Deploy Site

Deploy the client's tenant site to Workers for Platforms.

Phase 11+12: pass dry_run=true to receive a preview URL and confirm_token without deploying; pass confirm_token=<cft_…> to consume the prior preview and deploy to production. Calls without either flag keep today's immediate behaviour (back-compat until Stage 4 rollout flips the default).

domain=<host> (Bug #4) scopes which of the workspace's domains get their CF DOMAIN_MAP entry + Worker Route refreshed, so a deploy no longer silently re-touches a sibling domain's routing. Unknown host → 400.

Parameters

NameInTypeRequiredDescription
dry_runquerybooleanfalsePhase 11+12: issue a preview + confirm_token without deploying.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and deploy to production.
domainqueryanyfalseBug #4: scope the DOMAIN_MAP/route fan-out to a single host of this workspace (else all of the active project's domains).
Try it
Query

Examples

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

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/deploy",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/deploy", {
  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/content/deploy", 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/content/deploy/preview

Deploy Site Preview

Phase 11+12 Stage 2 — issue a preview URL + confirm_token for the proposed deploy. No CF production script upload, no DNS flip. Caller reviews the preview, then calls POST /deploy/production with the confirm_token to actually deploy.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/deploy/preview' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/deploy/preview",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/deploy/preview", {
  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/content/deploy/preview", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
POST/api/v1/dashboard/content/deploy/production

Deploy Site Production

Phase 11+12 Stage 2 — consume a prior preview's confirm_token (Lock 4) and run the real deploy. 403 on tenant/action/resource mismatch, 410 on expired, 409 on already-consumed replay.

domain=<host> (Bug #4) scopes the routing fan-out to a single host.

Parameters

NameInTypeRequiredDescription
confirm_tokenquerystringtrueToken from a prior /deploy/preview call.
domainqueryanyfalseBug #4: scope the DOMAIN_MAP/route fan-out to a single host of this workspace (else all of the active project's domains).
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/deploy/production' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/deploy/production",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/deploy/production", {
  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/content/deploy/production", 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/content/deploy/status

Get Deploy Status

Get the most recent deploy status for this client.

Try it

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/deploy/status",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/deploy/status", {
  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/content/deploy/status", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
GET/api/v1/dashboard/content/deploy/history

List Deploys

List recent deploys for this client.

Parameters

NameInTypeRequiredDescription
limitqueryintegerfalse
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/deploy/history",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/deploy/history", {
  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/content/deploy/history", 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/content/deploy/readiness

Get Deploy Readiness

Check if this client's site is ready to deploy.

Returns a checklist of prerequisites (settings, domain, templates, pages) with pass/fail status and actionable fix instructions. Blocking items prevent deploy; warnings are advisory.

Try it

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/deploy/readiness",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/deploy/readiness", {
  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/content/deploy/readiness", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
GET/api/v1/dashboard/content/deploy/{deploy_id}

Get Deploy Detail

Full detail for a single deploy — backs the per-deploy detail page.

Client-scoped: returns 404 if the deploy doesn't exist OR belongs to a different tenant (no cross-tenant leakage). Computes duration_ms from deployed_at − created_at. Declared AFTER the static /deploy/* routes so {deploy_id} never shadows status/history/readiness.

Parameters

NameInTypeRequiredDescription
deploy_idpathstringtrue
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/deploy/{deploy_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/deploy/{deploy_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/content/deploy/{deploy_id}", 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/content/changelog

List Changelog

List changelog entries (newest first).

Drafts are included for the editor surface. Paginated — the public feed + timeline read the same service method with include_drafts=False.

Parameters

NameInTypeRequiredDescription
statusqueryanyfalseFilter by status (draft / published / archived).
pagequeryanyfalse1-based page number (house pattern; wins over limit/offset).
page_sizequeryanyfalseEntries per page (1-200, default 50).
limitqueryanyfalseLegacy alias for page_size. Kept for back-compat.
offsetqueryanyfalseLegacy alias — raw row offset. Kept for back-compat.
sortquerystringfalseOrdering, newest first. published_at (default) = release date. version = semver compared NUMERICALLY per component, so v2.10.0 sorts above v2.9.0 — use it when the entries were backfilled and their timestamps don't reflect true release order.
include_bodyquerybooleanfalseInclude each entry's full Tiptap body. Pass false for a light index (id/version/title/status/dates) — 25 entries with bodies is ~128k chars, which blows an agent's tool-output ceiling. Fetch a single body with GET /changelog/{entry_id}. Defaults true so the dashboard editor keeps its one-shot list→edit flow.
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/changelog",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/changelog", {
  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/content/changelog", 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/content/changelog

Create Changelog

Create a draft changelog entry (409 on a duplicate version).

published_at is optional and does NOT publish the entry — it pre-stamps the release date so a backfilled history lands in true order on the public timeline (which is ordered by date, never by version string).

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/changelog' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "version": "string",
  "title": "string",
  "body": {},
  "published_at": "2026-01-01T00:00:00Z"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/changelog",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"version": "string", "title": "string", "body": {}, "published_at": "2026-01-01T00:00:00Z"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/changelog", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"version": "string", "title": "string", "body": {}, "published_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(`{"version": "string", "title": "string", "body": {}, "published_at": "2026-01-01T00:00:00Z"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/changelog", 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/content/changelog/{entry_id}

Get Changelog

Get one changelog entry by ID (drafts included).

Parameters

NameInTypeRequiredDescription
entry_idpathstringtrue
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_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/content/changelog/{entry_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/content/changelog/{entry_id}

Update Changelog

Update a changelog entry's title/body (version is immutable post-create only via this route's schema; pass it through update_changelog if needed).

Parameters

NameInTypeRequiredDescription
entry_idpathstringtrue
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "version": "string",
  "title": "string",
  "body": {},
  "published_at": "2026-01-01T00:00:00Z"
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"version": "string", "title": "string", "body": {}, "published_at": "2026-01-01T00:00:00Z"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"version": "string", "title": "string", "body": {}, "published_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(`{"version": "string", "title": "string", "body": {}, "published_at": "2026-01-01T00:00:00Z"}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_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/content/changelog/{entry_id}

Delete Changelog

Soft-delete a changelog entry (status → archived). Returns 204.

Parameters

NameInTypeRequiredDescription
entry_idpathstringtrue
Try it
Query

Examples

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

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_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/content/changelog/{entry_id}", 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/content/changelog/{entry_id}/publish

Publish Changelog

Publish a changelog entry (fires changelog.published on first publish).

The body is OPTIONAL — with none, the entry is stamped NOW() exactly as before. Send {"published_at": "..."} to publish a historical entry with its real release date; it wins over any date already on the entry.

Parameters

NameInTypeRequiredDescription
entry_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_id}/publish' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "published_at": "2026-01-01T00:00:00Z"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_id}/publish",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"published_at": "2026-01-01T00:00:00Z"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_id}/publish", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"published_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(`{"published_at": "2026-01-01T00:00:00Z"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_id}/publish", 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/content/changelog/{entry_id}/unpublish

Unpublish Changelog

Revert a changelog entry to draft.

Parameters

NameInTypeRequiredDescription
entry_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_id}/unpublish' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_id}/unpublish",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/changelog/{entry_id}/unpublish", {
  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/content/changelog/{entry_id}/unpublish", 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/content/audit/links

Audit Internal Links

Walk every published page's blocks + navigation menus and validate internal links against the published-page roster + active redirects.

Returns {valid_count, broken: [{path, source, reason}], proposed_redirects, known_redirects}.

Fixes the Unavis-report pain: cleaning up /en/* legacy URLs across nav + blocks used to require manual crawling. One call surfaces every broken link with its exact source so agents can propose redirects in a single pass.

Try it

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/content/audit/links",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/audit/links", {
  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/content/audit/links", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
GET/api/v1/dashboard/projects/{project_id}/content/pages

List Pages

List all content pages (including drafts). Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

NameInTypeRequiredDescription
pagequeryintegerfalse
page_sizequeryintegerfalse
statusqueryanyfalse
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages", {
  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/projects/{project_id}/content/pages", 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/projects/{project_id}/content/pages

Create Page

Create a new content page. Phase 11+12 dry_run/confirm_token gated.

Parameters

NameInTypeRequiredDescription
dry_runquerybooleanfalsePhase 11+12: preview the create and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the create.
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "slug": "string",
  "title": "string",
  "description": "string",
  "agent_strategy": "string",
  "agent_flow_id": "string",
  "geo_ai_summary": "string",
  "geo_ai_crawlers": "string",
  "seo_title": "string",
  "seo_description": "string",
  "og_title": "string",
  "og_description": "string",
  "og_image_url": "string",
  "twitter_card": "string",
  "twitter_image_url": "string",
  "canonical_url": "string",
  "robots": "string",
  "keywords": "string",
  "json_ld": {},
  "blocks": [
    {
      "id": "string",
      "type": "hero",
      "data": {},
      "component_slug": "string",
      "component_version": "string",
      "props": {},
      "layout": "string",
      "data_binding": {}
    }
  ],
  "template": "default"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"slug": "string", "title": "string", "description": "string", "agent_strategy": "string", "agent_flow_id": "string", "geo_ai_summary": "string", "geo_ai_crawlers": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "blocks": [{"id": "string", "type": "hero", "data": {}, "component_slug": "string", "component_version": "string", "props": {}, "layout": "string", "data_binding": {}}], "template": "default"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"slug": "string", "title": "string", "description": "string", "agent_strategy": "string", "agent_flow_id": "string", "geo_ai_summary": "string", "geo_ai_crawlers": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "blocks": [{"id": "string", "type": "hero", "data": {}, "component_slug": "string", "component_version": "string", "props": {}, "layout": "string", "data_binding": {}}], "template": "default"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"slug": "string", "title": "string", "description": "string", "agent_strategy": "string", "agent_flow_id": "string", "geo_ai_summary": "string", "geo_ai_crawlers": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "blocks": [{"id": "string", "type": "hero", "data": {}, "component_slug": "string", "component_version": "string", "props": {}, "layout": "string", "data_binding": {}}], "template": "default"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages", 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/projects/{project_id}/content/pages/{page_id}

Get Page

Get a page by ID. Use ?format=json|yaml|md|llm for agent-friendly responses.

P5: pass ?audit_level=off|errors|warnings|all to control the _page_audit decoration. Default 'warnings' returns errors + warnings in the audit block.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
audit_levelquerystringfalseP5: include a _page_audit block on the response. 'off' skips the auditor entirely (cheapest). 'errors' / 'warnings' / 'all' filter by severity. Default 'warnings' — agent-friendly.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_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/projects/{project_id}/content/pages/{page_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/projects/{project_id}/content/pages/{page_id}

Update Page

Update a page. Phase 11+12 dry_run/confirm_token gated. P4 lock-aware.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the update and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the update.
forcequerybooleanfalseP4: bypass page lock (super_admin / brand_admin only).
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "agent_strategy": "string",
  "agent_flow_id": "string",
  "geo_ai_summary": "string",
  "geo_ai_crawlers": "string",
  "seo_title": "string",
  "seo_description": "string",
  "og_title": "string",
  "og_description": "string",
  "og_image_url": "string",
  "twitter_card": "string",
  "twitter_image_url": "string",
  "canonical_url": "string",
  "robots": "string",
  "keywords": "string",
  "json_ld": {},
  "title": "string",
  "description": "string",
  "blocks": [
    {
      "id": "string",
      "type": "hero",
      "data": {},
      "component_slug": "string",
      "component_version": "string",
      "props": {},
      "layout": "string",
      "data_binding": {}
    }
  ],
  "template": "string",
  "collection_type": "string"
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"agent_strategy": "string", "agent_flow_id": "string", "geo_ai_summary": "string", "geo_ai_crawlers": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "title": "string", "description": "string", "blocks": [{"id": "string", "type": "hero", "data": {}, "component_slug": "string", "component_version": "string", "props": {}, "layout": "string", "data_binding": {}}], "template": "string", "collection_type": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"agent_strategy": "string", "agent_flow_id": "string", "geo_ai_summary": "string", "geo_ai_crawlers": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "title": "string", "description": "string", "blocks": [{"id": "string", "type": "hero", "data": {}, "component_slug": "string", "component_version": "string", "props": {}, "layout": "string", "data_binding": {}}], "template": "string", "collection_type": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"agent_strategy": "string", "agent_flow_id": "string", "geo_ai_summary": "string", "geo_ai_crawlers": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "title": "string", "description": "string", "blocks": [{"id": "string", "type": "hero", "data": {}, "component_slug": "string", "component_version": "string", "props": {}, "layout": "string", "data_binding": {}}], "template": "string", "collection_type": "string"}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_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/projects/{project_id}/content/pages/{page_id}

Delete Page

Archive a page (soft delete). Phase 11+12 dry_run/confirm_token gated. P4 lock-aware.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the delete.
forcequerybooleanfalseP4: bypass page lock (super_admin / brand_admin only).
Try it
Query

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_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/projects/{project_id}/content/pages/{page_id}", 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/projects/{project_id}/content/pages/{page_id}/preview

Page Preview

Issue a short-lived iframe preview URL for the in-flight blocks the editor is currently showing. The URL is loaded by the Page Editor iframe; the Liquid renderer reads the token via __spideriq_preview_token query param and substitutes page.blocks with the supplied draft before rendering.

Tokens expire in 15 minutes — the editor will refetch on focus/edit. Lock 1 ↔ Lock 5: tenancy is enforced by validating the page belongs to the caller's resolved client_id; the snapshot stored in Redis carries the resolved client_id, not anything from the URL.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/preview' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "blocks": [
    {
      "type": "string",
      "data": {}
    }
  ],
  "draft_mode": true
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/preview",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"blocks": [{"type": "string", "data": {}}], "draft_mode": true},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/preview", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"blocks": [{"type": "string", "data": {}}], "draft_mode": true})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"blocks": [{"type": "string", "data": {}}], "draft_mode": true}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/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/projects/{project_id}/content/posts/{post_id}/preview

Post Preview

Issue a short-lived, token-gated preview URL for a DRAFT blog post.

Draft posts 404 at /blog/<slug> on the live site (the public API serves published-only), so a human reviewer can't see one before publish. This mints an opaque 15-minute token bound to (client_id, slug); the returned URL proxies the tenant's deployed Liquid renderer at /blog/<slug> with the token, and the renderer substitutes the fresh draft post (noindex, no-store).

Lock 1 ↔ Lock 5: the post is fetched scoped to the caller's resolved client_id; the Redis snapshot stores that client_id, never anything from the URL. Works for any status (draft/published) — most useful for drafts.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/preview' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/preview",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/preview", {
  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/projects/{project_id}/content/posts/{post_id}/preview", 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/projects/{project_id}/content/pages/{page_id}/publish

Publish Page

Publish a page (creates version snapshot). Phase 11+12 dry_run/confirm_token gated. P4 lock-aware.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the publish.
forcequerybooleanfalseP4: bypass page lock (super_admin / brand_admin only).
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/publish' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/publish",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/publish", {
  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/projects/{project_id}/content/pages/{page_id}/publish", 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/projects/{project_id}/content/pages/{page_id}/duplicate

Duplicate Page

Duplicate a page. New row: status='draft', fresh UUIDs on every block, auto-generated slug (or caller-provided new_slug). The copy is always owned by the caller's client — no cross-tenant duplication via this endpoint.

Enables the Apr-24 catalog-triage follow-on work (template gallery, section library, import adapters all build on this primitive).

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/duplicate' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/duplicate",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/duplicate", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/duplicate", 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
POST/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/blocks/{block_id}/duplicate

Duplicate Page Block

Insert a deep copy of one block into the same page. Fresh UUID on the new block; same data/props/component_slug as the source.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
block_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/blocks/{block_id}/duplicate' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "position": "after"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/blocks/{block_id}/duplicate",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"position": "after"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/blocks/{block_id}/duplicate", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"position": "after"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"position": "after"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/blocks/{block_id}/duplicate", 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/projects/{project_id}/content/pages/{page_id}/insert-section

Insert Section Into Page Endpoint

Insert a marketplace section into an existing page (Phase C).

Request body matches InsertSectionRequest: { component_slug, component_version?, props?, position?, anchor_block_id?, data_binding?, layout_id? }

Phase 11+12 gated. dry_run=true returns the preview envelope; confirm_token consumes it and performs the mutation.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the insertion and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and apply the insertion.
forcequerybooleanfalseP4: bypass page lock (super_admin / brand_admin only).
audit_levelquerystringfalseP5: include an _audit block on the success response. Default 'all' for mutations so agents see every finding immediately. 'off' is available for tight-loop scripts that bulk-insert and audit later.
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/insert-section' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/insert-section",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/insert-section", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/insert-section", 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/projects/{project_id}/content/pages/{page_id}/unpublish

Unpublish Page

Revert page to draft status. Phase 11+12 dry_run/confirm_token gated. P4 lock-aware.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the unpublish.
forcequerybooleanfalseP4: bypass page lock (super_admin / brand_admin only).
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/unpublish' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/unpublish",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/unpublish", {
  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/projects/{project_id}/content/pages/{page_id}/unpublish", 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/projects/{project_id}/content/pages/{page_id}/versions

Get Page Versions

List version snapshots for a page (newest first).

P4: each row reports block_count + blocks_size so the editor can summarise without round-tripping the full snapshot. Use GET /pages/{id}/versions/{version_number} to fetch a single snapshot in full (with blocks).

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/versions' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/versions",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/versions", {
  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/projects/{project_id}/content/pages/{page_id}/versions", 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/projects/{project_id}/content/pages/{page_id}/versions/{version_number}

Get Page Version

Fetch a single page version snapshot in full (includes blocks).

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
version_numberpathintegertrue
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/versions/{version_number}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/versions/{version_number}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/versions/{version_number}", {
  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/projects/{project_id}/content/pages/{page_id}/versions/{version_number}", 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/projects/{project_id}/content/pages/{page_id}/lock

Lock Page Endpoint

Lock a page against further mutations.

P4 — agent-surface hardening. Idempotent: re-locking refreshes the reason/timestamp. Any role with content-scoped access can lock; unlock authorisation is more restrictive (lock-holder OR force=true with super_admin / brand_admin).

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/lock' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/lock",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/lock", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/lock", 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
423Page already locked
422Validation Error
POST/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/unlock

Unlock Page Endpoint

Unlock a page.

Authorisation:

  • Anyone whose user_id matches locked_by_actor_id can unlock.
  • super_admin / brand_admin can unlock with ?force=true.
  • Otherwise: 403 (force gate) or "Page not found / not authorised" (200 with the unchanged row would be a misleading response — we 404 so the caller distinguishes "the page doesn't exist" from "it's locked by someone else", since the latter is itself the answer to the permission question).

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
forcequerybooleanfalsesuper_admin / brand_admin override — unlock regardless of who locked.
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/unlock' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/unlock",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/unlock", {
  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/projects/{project_id}/content/pages/{page_id}/unlock", 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/projects/{project_id}/content/pages/{page_id}/restore

Restore Page Version Endpoint

Restore a page to a historical version snapshot.

Phase 11+12 gated. dry_run=true returns a preview envelope with the snapshot summary. The page lock is enforced — call with force=true (super_admin / brand_admin) to override.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
version_numberqueryintegertrueWhich version to restore (1-indexed).
dry_runquerybooleanfalsePhase 11+12: preview the restore + receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the restore.
forcequerybooleanfalseP4: bypass page lock (super_admin / brand_admin only).
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/restore' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/restore",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/restore", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/restore", 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/projects/{project_id}/content/pages/{page_id}/export

Export Page

Self-contained page export with audit (P2 — agent-surface hardening).

Returns the page row + every component referenced by page.blocks (full body inlined: html_template / js / css / props_schema / dependencies / agent_meta / kind / layouts) + site-level settings + domains + a PageAuditor walk over the same data.

Three formats:

  • format=json (default) — flat JSON envelope
  • format=md — human-readable Markdown (text/markdown)
  • format=archive — ZIP byte stream (application/zip), VSCode-extension-compatible

The page must belong to the caller's client_id (Lock 5 — same multi-tenant scope as GET /pages/{id}).

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
formatqueryanyfalsejson (default) and llm return the flat JSON envelope; md returns human-readable Markdown; archive returns a ZIP whose layout matches the VSCode extension's local format.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/export' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/export",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/export", {
  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/projects/{project_id}/content/pages/{page_id}/export", 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/projects/{project_id}/content/posts

List Posts

List all blog posts (including drafts). Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

NameInTypeRequiredDescription
pagequeryintegerfalse
page_sizequeryintegerfalse
statusqueryanyfalse
tagqueryanyfalse
categoryqueryanyfalseFilter by category id
author_idqueryanyfalseFilter by author (byline) id
created_byqueryanyfalseFilter by record creator / agent id
created_afterqueryanyfalseOnly posts published-or-created on/after this ISO timestamp (time-window filter)
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts", {
  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/projects/{project_id}/content/posts", 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/projects/{project_id}/content/posts

Create Post

Create a new blog post. Phase 11+12 dry_run/confirm_token gated.

Unknown fields in the request body are silently dropped by Pydantic (extra='ignore' default) but surfaced in warnings[] on the response with a "Did you mean X?" hint. Catches the common cover_image vs cover_image_url / category_id vs category_ids / featured vs is_featured confusions that AI agents fall into.

Parameters

NameInTypeRequiredDescription
dry_runquerybooleanfalsePhase 11+12: preview the create and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the create.
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "slug": "string",
  "title": "string",
  "excerpt": "string",
  "agent_strategy": "string",
  "agent_flow_id": "string",
  "body": {},
  "cover_image_url": "string",
  "author_name": "string",
  "author_id": "00000000-0000-0000-0000-000000000000",
  "tags": [
    "string"
  ],
  "tag_ids": [
    "00000000-0000-0000-0000-000000000000"
  ],
  "category_ids": [
    "00000000-0000-0000-0000-000000000000"
  ],
  "is_featured": false,
  "featured_image_alt": "string",
  "tldr_summary": "string",
  "related_post_ids": [
    "00000000-0000-0000-0000-000000000000"
  ],
  "seo_title": "string",
  "seo_description": "string",
  "og_image_url": "string",
  "custom_fields": {}
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"slug": "string", "title": "string", "excerpt": "string", "agent_strategy": "string", "agent_flow_id": "string", "body": {}, "cover_image_url": "string", "author_name": "string", "author_id": "00000000-0000-0000-0000-000000000000", "tags": ["string"], "tag_ids": ["00000000-0000-0000-0000-000000000000"], "category_ids": ["00000000-0000-0000-0000-000000000000"], "is_featured": false, "featured_image_alt": "string", "tldr_summary": "string", "related_post_ids": ["00000000-0000-0000-0000-000000000000"], "seo_title": "string", "seo_description": "string", "og_image_url": "string", "custom_fields": {}},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"slug": "string", "title": "string", "excerpt": "string", "agent_strategy": "string", "agent_flow_id": "string", "body": {}, "cover_image_url": "string", "author_name": "string", "author_id": "00000000-0000-0000-0000-000000000000", "tags": ["string"], "tag_ids": ["00000000-0000-0000-0000-000000000000"], "category_ids": ["00000000-0000-0000-0000-000000000000"], "is_featured": false, "featured_image_alt": "string", "tldr_summary": "string", "related_post_ids": ["00000000-0000-0000-0000-000000000000"], "seo_title": "string", "seo_description": "string", "og_image_url": "string", "custom_fields": {}})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"slug": "string", "title": "string", "excerpt": "string", "agent_strategy": "string", "agent_flow_id": "string", "body": {}, "cover_image_url": "string", "author_name": "string", "author_id": "00000000-0000-0000-0000-000000000000", "tags": ["string"], "tag_ids": ["00000000-0000-0000-0000-000000000000"], "category_ids": ["00000000-0000-0000-0000-000000000000"], "is_featured": false, "featured_image_alt": "string", "tldr_summary": "string", "related_post_ids": ["00000000-0000-0000-0000-000000000000"], "seo_title": "string", "seo_description": "string", "og_image_url": "string", "custom_fields": {}}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts", 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/projects/{project_id}/content/posts/{post_id}

Get Post

Get a post by ID. Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_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/projects/{project_id}/content/posts/{post_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/projects/{project_id}/content/posts/{post_id}

Update Post

Update a blog post. Phase 11+12 dry_run/confirm_token gated.

Unknown fields in the request body are silently dropped by Pydantic but surfaced in warnings[] on the response with a "Did you mean X?" hint. Catches the common cover_image vs cover_image_url / category_id vs category_ids / featured vs is_featured confusions.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the update and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the update.
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "agent_strategy": "string",
  "agent_flow_id": "string",
  "title": "string",
  "slug": "string",
  "excerpt": "string",
  "body": {},
  "cover_image_url": "string",
  "author_name": "string",
  "author_id": "00000000-0000-0000-0000-000000000000",
  "tags": [
    "string"
  ],
  "tag_ids": [
    "00000000-0000-0000-0000-000000000000"
  ],
  "category_ids": [
    "00000000-0000-0000-0000-000000000000"
  ],
  "is_featured": true,
  "featured_image_alt": "string",
  "tldr_summary": "string",
  "related_post_ids": [
    "00000000-0000-0000-0000-000000000000"
  ],
  "seo_title": "string",
  "seo_description": "string",
  "og_image_url": "string",
  "custom_fields": {}
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"agent_strategy": "string", "agent_flow_id": "string", "title": "string", "slug": "string", "excerpt": "string", "body": {}, "cover_image_url": "string", "author_name": "string", "author_id": "00000000-0000-0000-0000-000000000000", "tags": ["string"], "tag_ids": ["00000000-0000-0000-0000-000000000000"], "category_ids": ["00000000-0000-0000-0000-000000000000"], "is_featured": true, "featured_image_alt": "string", "tldr_summary": "string", "related_post_ids": ["00000000-0000-0000-0000-000000000000"], "seo_title": "string", "seo_description": "string", "og_image_url": "string", "custom_fields": {}},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"agent_strategy": "string", "agent_flow_id": "string", "title": "string", "slug": "string", "excerpt": "string", "body": {}, "cover_image_url": "string", "author_name": "string", "author_id": "00000000-0000-0000-0000-000000000000", "tags": ["string"], "tag_ids": ["00000000-0000-0000-0000-000000000000"], "category_ids": ["00000000-0000-0000-0000-000000000000"], "is_featured": true, "featured_image_alt": "string", "tldr_summary": "string", "related_post_ids": ["00000000-0000-0000-0000-000000000000"], "seo_title": "string", "seo_description": "string", "og_image_url": "string", "custom_fields": {}})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"agent_strategy": "string", "agent_flow_id": "string", "title": "string", "slug": "string", "excerpt": "string", "body": {}, "cover_image_url": "string", "author_name": "string", "author_id": "00000000-0000-0000-0000-000000000000", "tags": ["string"], "tag_ids": ["00000000-0000-0000-0000-000000000000"], "category_ids": ["00000000-0000-0000-0000-000000000000"], "is_featured": true, "featured_image_alt": "string", "tldr_summary": "string", "related_post_ids": ["00000000-0000-0000-0000-000000000000"], "seo_title": "string", "seo_description": "string", "og_image_url": "string", "custom_fields": {}}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_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/projects/{project_id}/content/posts/{post_id}

Delete Post

Delete a blog post. Phase 11+12 dry_run/confirm_token gated.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the delete and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the delete.
Try it
Query

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_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/projects/{project_id}/content/posts/{post_id}", 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/projects/{project_id}/content/posts/{post_id}/publish

Publish Post

Publish a blog post.

Body is OPTIONAL. published_at backdates the publication (archive import); for a FUTURE go-live use POST /posts/{id}/schedule instead.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/publish' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "published_at": "2026-01-01T00:00:00Z"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/publish",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"published_at": "2026-01-01T00:00:00Z"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/publish", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"published_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(`{"published_at": "2026-01-01T00:00:00Z"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/publish", 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/projects/{project_id}/content/posts/{post_id}/unpublish

Unpublish Post

Unpublish a blog post (set to draft).

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/unpublish' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/unpublish",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/unpublish", {
  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/projects/{project_id}/content/posts/{post_id}/unpublish", 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/projects/{project_id}/content/posts/{post_id}/schedule

Schedule Post

Schedule a post to auto-publish at a future time (status='scheduled').

The scheduler sidecar flips it to 'published' once the time arrives. Public surfaces gate on status='published', so a scheduled post stays private until then. A non-future time is rejected — use /publish for immediate publish.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/schedule' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "published_at": "2026-01-01T00:00:00Z"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/schedule",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"published_at": "2026-01-01T00:00:00Z"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/schedule", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"published_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(`{"published_at": "2026-01-01T00:00:00Z"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/schedule", 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/projects/{project_id}/content/posts/{post_id}/unschedule

Unschedule Post

Cancel a scheduled publish — revert the post to draft.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/unschedule' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/unschedule",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/unschedule", {
  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/projects/{project_id}/content/posts/{post_id}/unschedule", 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/projects/{project_id}/content/posts/{post_id}/duplicate

Duplicate Post

Duplicate a blog post. Returns the new draft with a fresh slug + UUID.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/duplicate' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/duplicate",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/duplicate", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/duplicate", 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
POST/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/status

Update Post Status

Update post status (draft, pending_review, published, archived).

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/status' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "status": "draft"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/status",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"status": "draft"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/status", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"status": "draft"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"status": "draft"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/status", 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
PUT/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/related

Update Post Related

Set related posts for a post.

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X PUT 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/related' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '[
  "string"
]'
Python
import httpx

resp = httpx.put(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/related",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json=["string"],
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/related", {
  method: "PUT",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify(["string"])
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`["string"]`)
	req, _ := http.NewRequest("PUT", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/related", 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/projects/{project_id}/content/authors

List Authors

List all authors. Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

NameInTypeRequiredDescription
pagequeryintegerfalse
page_sizequeryintegerfalse
agent_typequeryanyfalse
is_activequeryanyfalse
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/authors' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/authors",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/authors", {
  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/projects/{project_id}/content/authors", 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/projects/{project_id}/content/authors

Create Author

Create a new author.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/authors' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "full_name": "string",
  "slug": "string",
  "avatar_url": "string",
  "bio": "string",
  "email": "string",
  "role": "author",
  "agent_type": "human",
  "country": "string",
  "city": "string"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/authors",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"full_name": "string", "slug": "string", "avatar_url": "string", "bio": "string", "email": "string", "role": "author", "agent_type": "human", "country": "string", "city": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/authors", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"full_name": "string", "slug": "string", "avatar_url": "string", "bio": "string", "email": "string", "role": "author", "agent_type": "human", "country": "string", "city": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"full_name": "string", "slug": "string", "avatar_url": "string", "bio": "string", "email": "string", "role": "author", "agent_type": "human", "country": "string", "city": "string"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/authors", 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/projects/{project_id}/content/authors/{author_id}

Get Author

Get an author by ID. Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

NameInTypeRequiredDescription
author_idpathstringtrue
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/authors/{author_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/authors/{author_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/authors/{author_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/projects/{project_id}/content/authors/{author_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/projects/{project_id}/content/authors/{author_id}

Update Author

Update an author.

Parameters

NameInTypeRequiredDescription
author_idpathstringtrue
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/authors/{author_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "full_name": "string",
  "slug": "string",
  "avatar_url": "string",
  "bio": "string",
  "email": "string",
  "role": "author",
  "agent_type": "human",
  "country": "string",
  "city": "string",
  "is_active": true
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/authors/{author_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"full_name": "string", "slug": "string", "avatar_url": "string", "bio": "string", "email": "string", "role": "author", "agent_type": "human", "country": "string", "city": "string", "is_active": true},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/authors/{author_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"full_name": "string", "slug": "string", "avatar_url": "string", "bio": "string", "email": "string", "role": "author", "agent_type": "human", "country": "string", "city": "string", "is_active": true})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"full_name": "string", "slug": "string", "avatar_url": "string", "bio": "string", "email": "string", "role": "author", "agent_type": "human", "country": "string", "city": "string", "is_active": true}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/authors/{author_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/projects/{project_id}/content/authors/{author_id}

Delete Author

Deactivate an author (soft-delete).

Parameters

NameInTypeRequiredDescription
author_idpathstringtrue
Try it
Query

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/authors/{author_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/authors/{author_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/authors/{author_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/projects/{project_id}/content/authors/{author_id}", 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/projects/{project_id}/content/tags

List Tags

List all tags. Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

NameInTypeRequiredDescription
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/tags' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/tags",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/tags", {
  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/projects/{project_id}/content/tags", 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/projects/{project_id}/content/tags

Create Tag

Create a new tag.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/tags' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "slug": "string",
  "description": "string"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/tags",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "slug": "string", "description": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/tags", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "slug": "string", "description": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "slug": "string", "description": "string"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/tags", 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
PATCH/api/v1/dashboard/projects/{project_id}/content/tags/{tag_id}

Update Tag

Update a tag.

Parameters

NameInTypeRequiredDescription
tag_idpathstringtrue
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/tags/{tag_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "slug": "string",
  "description": "string"
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/tags/{tag_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "slug": "string", "description": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/tags/{tag_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "slug": "string", "description": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "slug": "string", "description": "string"}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/tags/{tag_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/projects/{project_id}/content/tags/{tag_id}

Delete Tag

Delete a tag.

Parameters

NameInTypeRequiredDescription
tag_idpathstringtrue
Try it
Query

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/tags/{tag_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/tags/{tag_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/tags/{tag_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/projects/{project_id}/content/tags/{tag_id}", 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/projects/{project_id}/content/categories

List Categories

List blog categories. Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

NameInTypeRequiredDescription
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/categories' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/categories",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/categories", {
  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/projects/{project_id}/content/categories", 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/projects/{project_id}/content/categories

Create Category

Create a new category.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/categories' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "slug": "string",
  "description": "string",
  "parent_id": "00000000-0000-0000-0000-000000000000",
  "sort_order": 0
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/categories",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "slug": "string", "description": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/categories", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "slug": "string", "description": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "slug": "string", "description": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/categories", 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
PATCH/api/v1/dashboard/projects/{project_id}/content/categories/{category_id}

Update Category

Update a category.

Parameters

NameInTypeRequiredDescription
category_idpathstringtrue
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/categories/{category_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "slug": "string",
  "description": "string",
  "parent_id": "00000000-0000-0000-0000-000000000000",
  "sort_order": 0
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/categories/{category_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "slug": "string", "description": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/categories/{category_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "slug": "string", "description": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "slug": "string", "description": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/categories/{category_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/projects/{project_id}/content/categories/{category_id}

Delete Category

Delete a category.

Parameters

NameInTypeRequiredDescription
category_idpathstringtrue
Try it
Query

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/categories/{category_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/categories/{category_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/categories/{category_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/projects/{project_id}/content/categories/{category_id}", 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/projects/{project_id}/content/docs/tree

Get Docs Tree

Get full docs tree (including drafts).

Docs Platform v2 · 3.4 — ?version= scopes the editor tree to one docs version (omit → default). Response carries all versions (every status, for management) + the resolved current_version.

Parameters

NameInTypeRequiredDescription
versionqueryanyfalse
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/tree' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/tree",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/tree", {
  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/projects/{project_id}/content/docs/tree", 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/projects/{project_id}/content/docs

List Docs

Flat list of docs (metadata only, no body) — complements GET /docs/tree.

Agents use this to discover a doc's UUID by title/status before fetching or mutating it via GET /docs/{doc_id}.

Parameters

NameInTypeRequiredDescription
statusqueryanyfalseFilter by status (draft / published / archived).
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs", {
  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/projects/{project_id}/content/docs", 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/projects/{project_id}/content/docs

Create Doc

Create a documentation page.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "agent_strategy": "string",
  "agent_flow_id": "string",
  "seo_title": "string",
  "seo_description": "string",
  "og_title": "string",
  "og_description": "string",
  "og_image_url": "string",
  "twitter_card": "string",
  "twitter_image_url": "string",
  "canonical_url": "string",
  "robots": "string",
  "keywords": "string",
  "json_ld": {},
  "parent_id": "00000000-0000-0000-0000-000000000000",
  "slug": "string",
  "title": "string",
  "body": {},
  "is_section": false,
  "sort_order": 0,
  "version": "default"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"agent_strategy": "string", "agent_flow_id": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "parent_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "body": {}, "is_section": false, "sort_order": 0, "version": "default"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"agent_strategy": "string", "agent_flow_id": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "parent_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "body": {}, "is_section": false, "sort_order": 0, "version": "default"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"agent_strategy": "string", "agent_flow_id": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "parent_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "body": {}, "is_section": false, "sort_order": 0, "version": "default"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs", 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/projects/{project_id}/content/docs/versions

List Doc Versions

List the tenant's docs versions (all statuses, for management).

Try it

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/versions' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/versions",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/versions", {
  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/projects/{project_id}/content/docs/versions", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
POST/api/v1/dashboard/projects/{project_id}/content/docs/versions

Create Doc Version

Register a new docs version label. is_default demotes the prior default.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/versions' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "label": "string",
  "title": "string",
  "is_default": false,
  "sort_order": 0,
  "status": "published"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/versions",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"label": "string", "title": "string", "is_default": false, "sort_order": 0, "status": "published"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/versions", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"label": "string", "title": "string", "is_default": false, "sort_order": 0, "status": "published"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"label": "string", "title": "string", "is_default": false, "sort_order": 0, "status": "published"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/versions", 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
PATCH/api/v1/dashboard/projects/{project_id}/content/docs/versions/{version_id}

Update Doc Version

Update a docs version (title / order / status / default flag).

Parameters

NameInTypeRequiredDescription
version_idpathstringtrue
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/versions/{version_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "title": "string",
  "is_default": true,
  "sort_order": 0,
  "status": "string"
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/versions/{version_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"title": "string", "is_default": true, "sort_order": 0, "status": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/versions/{version_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"title": "string", "is_default": true, "sort_order": 0, "status": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"title": "string", "is_default": true, "sort_order": 0, "status": "string"}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/versions/{version_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/projects/{project_id}/content/docs/versions/{version_id}

Delete Doc Version

Delete a docs version. Refuses the default version or one still in use.

Parameters

NameInTypeRequiredDescription
version_idpathstringtrue
Try it
Query

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/versions/{version_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/versions/{version_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/versions/{version_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/projects/{project_id}/content/docs/versions/{version_id}", 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/projects/{project_id}/content/docs/analytics

Get Docs Analytics

Server-side docs analytics overview (views / searches / asks) for the tenant over the last days. Degrades to an empty rollup, never 500s.

Parameters

NameInTypeRequiredDescription
daysqueryintegerfalse
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/analytics' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/analytics",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/analytics", {
  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/projects/{project_id}/content/docs/analytics", 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/projects/{project_id}/content/docs/{doc_id}

Get Doc

Get a doc by ID (drafts included).

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_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/projects/{project_id}/content/docs/{doc_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/projects/{project_id}/content/docs/{doc_id}

Update Doc

Update a doc (title, body, SEO, hierarchy). Phase 11+12 dry_run/confirm_token gated.

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the update and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the update.
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "agent_strategy": "string",
  "agent_flow_id": "string",
  "seo_title": "string",
  "seo_description": "string",
  "og_title": "string",
  "og_description": "string",
  "og_image_url": "string",
  "twitter_card": "string",
  "twitter_image_url": "string",
  "canonical_url": "string",
  "robots": "string",
  "keywords": "string",
  "json_ld": {},
  "parent_id": "00000000-0000-0000-0000-000000000000",
  "title": "string",
  "body": {},
  "is_section": true,
  "sort_order": 0
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"agent_strategy": "string", "agent_flow_id": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "parent_id": "00000000-0000-0000-0000-000000000000", "title": "string", "body": {}, "is_section": true, "sort_order": 0},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"agent_strategy": "string", "agent_flow_id": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "parent_id": "00000000-0000-0000-0000-000000000000", "title": "string", "body": {}, "is_section": true, "sort_order": 0})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"agent_strategy": "string", "agent_flow_id": "string", "seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "parent_id": "00000000-0000-0000-0000-000000000000", "title": "string", "body": {}, "is_section": true, "sort_order": 0}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_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/projects/{project_id}/content/docs/{doc_id}

Delete Doc

Archive a doc (soft delete). Phase 11+12 dry_run/confirm_token gated.

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the delete.
Try it
Query

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_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/projects/{project_id}/content/docs/{doc_id}", 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/projects/{project_id}/content/docs/{doc_id}/duplicate

Duplicate Doc

Duplicate a doc page. Copy lives as a sibling of the original under the same parent_id with a fresh slug. Status: draft.

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/duplicate' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/duplicate",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/duplicate", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/duplicate", 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
POST/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/publish

Publish Doc

Publish a draft doc. Phase 11+12 dry_run/confirm_token gated.

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the publish.
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/publish' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/publish",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/publish", {
  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/projects/{project_id}/content/docs/{doc_id}/publish", 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/projects/{project_id}/content/docs/{doc_id}/unpublish

Unpublish Doc

Revert a doc to draft status. Phase 11+12 dry_run/confirm_token gated.

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the unpublish.
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/unpublish' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/unpublish",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/unpublish", {
  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/projects/{project_id}/content/docs/{doc_id}/unpublish", 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/projects/{project_id}/content/docs/{doc_id}/export

Export Doc

Self-contained doc export. Returns the doc row + site settings + domains.

Docs are prose-first, so there are no component bodies to inline (unlike page export). The doc must belong to the caller's client_id.

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
formatqueryanyfalseResponse format. json (default) and llm return JSON; md returns text/markdown. This route has no YAML renderer, so yaml is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/export' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/export",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/export", {
  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/projects/{project_id}/content/docs/{doc_id}/export", 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/projects/{project_id}/content/docs/import

Import Doc Markdown

Import a doc from a Markdown body. Create a new doc (omit doc_id, provide slug + title) or replace an existing doc's body (set doc_id). :::component{...} directives become embedded component nodes.

Create delegates to create_doc (ungated); update delegates to the Phase 11+12 dry_run/confirm_token-gated update_doc.

Parameters

NameInTypeRequiredDescription
dry_runquerybooleanfalsePhase 11+12 (update path): preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12 (update path): consume a prior preview token and perform the update.
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/import' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "seo_title": "string",
  "seo_description": "string",
  "og_title": "string",
  "og_description": "string",
  "og_image_url": "string",
  "twitter_card": "string",
  "twitter_image_url": "string",
  "canonical_url": "string",
  "robots": "string",
  "keywords": "string",
  "json_ld": {},
  "markdown": "string",
  "doc_id": "00000000-0000-0000-0000-000000000000",
  "slug": "string",
  "title": "string",
  "parent_id": "00000000-0000-0000-0000-000000000000",
  "is_section": true,
  "sort_order": 0
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/import",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "markdown": "string", "doc_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "is_section": true, "sort_order": 0},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/import", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "markdown": "string", "doc_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "is_section": true, "sort_order": 0})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "markdown": "string", "doc_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "is_section": true, "sort_order": 0}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/import", 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/projects/{project_id}/content/docs/import-openapi

Import Openapi

Import an OpenAPI/Swagger spec into the docs tree. dry_run=true returns the planned section + pages without writing (powers the wizard preview); otherwise the reference is generated idempotently and (if publish) published.

Errors map to 422 (bad/oversized/unfetchable spec — message is client-safe) or 500 (logged, generic) — never leak the spec URL or upstream detail.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/import-openapi' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "source_url": "string",
  "spec_content": "string",
  "spec_format": "auto",
  "section": "api-reference",
  "publish": false,
  "dry_run": false
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/import-openapi",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"source_url": "string", "spec_content": "string", "spec_format": "auto", "section": "api-reference", "publish": false, "dry_run": false},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/import-openapi", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"source_url": "string", "spec_content": "string", "spec_format": "auto", "section": "api-reference", "publish": false, "dry_run": false})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"source_url": "string", "spec_content": "string", "spec_format": "auto", "section": "api-reference", "publish": false, "dry_run": false}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/import-openapi", 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/projects/{project_id}/content/docs/{doc_id}/markdown

Export Doc Markdown

Export a doc's body as pure Markdown (round-trips with POST /docs/import).

:::component{...} directives are preserved (render_tiptap_markdown emits them via serialize_component_node). The title is prepended as an H1. Distinct from /docs/{id}/export?format=md, which wraps the same body in a JSON envelope.

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/markdown' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/markdown",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/markdown", {
  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/projects/{project_id}/content/docs/{doc_id}/markdown", 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/projects/{project_id}/content/pages/import

Import Page Markdown

Import a page from a Markdown body — the markdown→page converter. Create a new page (omit page_id, provide slug + title) or replace an existing page's blocks (set page_id). Prose runs become rich_text blocks; :::component{...} directives become component blocks.

Delegates to the Phase 11+12 dry_run/confirm_token-gated create_page / update_page (the converter handler only does the markdown→blocks mapping).

Parameters

NameInTypeRequiredDescription
dry_runquerybooleanfalsePhase 11+12: preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the create/update.
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/import' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "seo_title": "string",
  "seo_description": "string",
  "og_title": "string",
  "og_description": "string",
  "og_image_url": "string",
  "twitter_card": "string",
  "twitter_image_url": "string",
  "canonical_url": "string",
  "robots": "string",
  "keywords": "string",
  "json_ld": {},
  "markdown": "string",
  "page_id": "00000000-0000-0000-0000-000000000000",
  "slug": "string",
  "title": "string",
  "template": "string",
  "parent_id": "00000000-0000-0000-0000-000000000000",
  "sort_order": 0
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/import",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "markdown": "string", "page_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "template": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/import", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "markdown": "string", "page_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "template": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"seo_title": "string", "seo_description": "string", "og_title": "string", "og_description": "string", "og_image_url": "string", "twitter_card": "string", "twitter_image_url": "string", "canonical_url": "string", "robots": "string", "keywords": "string", "json_ld": {}, "markdown": "string", "page_id": "00000000-0000-0000-0000-000000000000", "slug": "string", "title": "string", "template": "string", "parent_id": "00000000-0000-0000-0000-000000000000", "sort_order": 0}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/import", 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/projects/{project_id}/content/pages/{page_id}/markdown

Export Page Markdown

Export a page's blocks as pure Markdown (round-trips with POST /pages/import).

Component blocks serialize to :::component{...} directives (the converter contract — render_page_markdown(serialize_components=True)). This differs from /pages/{id}/export?format=md, which renders each component as a labelled human-readable section inside a JSON envelope (not round-trippable).

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/markdown' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/markdown",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/markdown", {
  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/projects/{project_id}/content/pages/{page_id}/markdown", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
422Validation Error
PUT/api/v1/dashboard/projects/{project_id}/content/docs/reorder

Reorder Docs

Reorder documentation tree.

Try it

Examples

cURL
curl -X PUT 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/reorder' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "items": [
    {}
  ]
}'
Python
import httpx

resp = httpx.put(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/reorder",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"items": [{}]},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/reorder", {
  method: "PUT",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"items": [{}]})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"items": [{}]}`)
	req, _ := http.NewRequest("PUT", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/reorder", 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/projects/{project_id}/content/navigation/{location}

Get Navigation

Get navigation menu.

D4 — the editor reads the RAW menu (expand=False, the service default). A folder-bound item must round-trip as its BINDING; expanding here would make the next save bake a frozen snapshot of the page tree into the JSONB.

Parameters

NameInTypeRequiredDescription
locationpathstringtrue
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/navigation/{location}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/navigation/{location}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/navigation/{location}", {
  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/projects/{project_id}/content/navigation/{location}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
422Validation Error
PUT/api/v1/dashboard/projects/{project_id}/content/navigation/{location}

Update Navigation

Update navigation menu.

Parameters

NameInTypeRequiredDescription
locationpathstringtrue
Try it
Query

Examples

cURL
curl -X PUT 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/navigation/{location}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "items": [
    {
      "label": "string",
      "url": "string",
      "icon": "string",
      "children": [],
      "is_external": false,
      "badge": "string",
      "source": {
        "kind": "site",
        "folder_id": {},
        "depth": 2
      }
    }
  ]
}'
Python
import httpx

resp = httpx.put(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/navigation/{location}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"items": [{"label": "string", "url": "string", "icon": "string", "children": [], "is_external": false, "badge": "string", "source": {"kind": "site", "folder_id": {}, "depth": 2}}]},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/navigation/{location}", {
  method: "PUT",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"items": [{"label": "string", "url": "string", "icon": "string", "children": [], "is_external": false, "badge": "string", "source": {"kind": "site", "folder_id": {}, "depth": 2}}]})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"items": [{"label": "string", "url": "string", "icon": "string", "children": [], "is_external": false, "badge": "string", "source": {"kind": "site", "folder_id": {}, "depth": 2}}]}`)
	req, _ := http.NewRequest("PUT", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/navigation/{location}", 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/projects/{project_id}/content/directory/categories

Dash List Directory Categories

List all directory categories for this client (includes drafts/empty ones).

Parameters

NameInTypeRequiredDescription
pagequeryintegerfalse
page_sizequeryintegerfalse
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories", {
  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/projects/{project_id}/content/directory/categories", 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/projects/{project_id}/content/directory/categories

Dash Create Directory Category

Create a directory category.

Body: {name, slug?, description?, icon?, seo_title_template?, seo_description_template?, template?, data_source?, sort_order?}

seo_*_template strings accept {category}, {city}, {listing} placeholders — rendered server-side on the public read endpoints.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories", 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/projects/{project_id}/content/directory/categories/{category_slug}

Dash Get Directory Category

Parameters

NameInTypeRequiredDescription
category_slugpathstringtrue
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}", {
  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/projects/{project_id}/content/directory/categories/{category_slug}", 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/projects/{project_id}/content/directory/categories/{category_slug}

Dash Update Directory Category

Parameters

NameInTypeRequiredDescription
category_slugpathstringtrue
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}", 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/projects/{project_id}/content/directory/categories/{category_slug}

Dash Delete Directory Category

Delete a category (cascades to its listings).

Parameters

NameInTypeRequiredDescription
category_slugpathstringtrue
Try it
Query

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}", {
  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/projects/{project_id}/content/directory/categories/{category_slug}", 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/projects/{project_id}/content/directory/categories/{category_slug}/listings/bulk

Dash Bulk Upsert Listings

Bulk upsert listings. Body: {listings: [{name, slug?, city, state?, ...}, ...]}.

Upsert semantics: slug unique per category. Missing slug auto-generated from name. Refreshes the materialized view + category counts on success.

Typical use: agent dumps the results of a SpiderMaps campaign into a category via a single call. Supports source_job_id so listings can be traced back to the job that produced them.

Parameters

NameInTypeRequiredDescription
category_slugpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}/listings/bulk' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}/listings/bulk",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}/listings/bulk", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}/listings/bulk", 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/projects/{project_id}/content/directory/listings

Dash List Directory Listings

List listings across categories. Filters: category_slug, city, status.

Parameters

NameInTypeRequiredDescription
category_slugqueryanyfalse
cityqueryanyfalse
statusquerystringfalse
pagequeryintegerfalse
page_sizequeryintegerfalse
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/listings' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/listings",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/listings", {
  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/projects/{project_id}/content/directory/listings", 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/projects/{project_id}/content/directory/categories/{category_slug}/listings

Dash Upsert Listing

Create or update a single listing in a category. Slug-based upsert.

Parameters

NameInTypeRequiredDescription
category_slugpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}/listings' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}/listings",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}/listings", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}/listings", 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/projects/{project_id}/content/directory/categories/{category_slug}/listings/{listing_slug}

Dash Delete Listing

Parameters

NameInTypeRequiredDescription
category_slugpathstringtrue
listing_slugpathstringtrue
Try it
Query

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}/listings/{listing_slug}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}/listings/{listing_slug}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}/listings/{listing_slug}", {
  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/projects/{project_id}/content/directory/categories/{category_slug}/listings/{listing_slug}", 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/projects/{project_id}/content/directory/categories/{category_slug}/import-from-idap

Dash Import From Idap

Populate a directory category from the tenant's IDAP data (norm_cli_*.businesses).

One call replaces the "run SpiderMaps → transform results → bulk_upsert" loop. The norm_cli_* schema is already the canonical store for every business SpiderIQ has seen for this tenant — this reads directly from it.

Every column the IDAP column manifest declares reaches the listing — typed columns land in typed columns, the rest land in the data jsonb under their frozen public field id.

Body (all optional): {category_filter: "Plumber", country_code: "US", city: "Miami", rating_min: 4.0, limit: 5000, prune: false}

prune: true ARCHIVES (never deletes) listings in this category whose source row no longer matches the filter — that is what makes a re-import honest, since the upsert is keyed on (category, slug) and a business deleted or renamed in IDAP otherwise leaves a stale published listing forever. It is OFF by default, and it refuses to run when the import hit its limit (a truncated result set cannot tell "gone" from "on the next page") — the refusal comes back as prune_skipped_reason.

Returns {upserted, inserted, updated, pruned, failed, source_rows, affected_cities, source_schema, fields_mapped, filter, sync_log_id, ...}.

Parameters

NameInTypeRequiredDescription
category_slugpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}/import-from-idap' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}/import-from-idap",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}/import-from-idap", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/categories/{category_slug}/import-from-idap", 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/projects/{project_id}/content/directory/refresh-stats

Dash Refresh Directory Stats

Manually refresh the city_stats materialized view. Normally auto-refreshed on bulk upsert.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/refresh-stats' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/refresh-stats",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/directory/refresh-stats", {
  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/projects/{project_id}/content/directory/refresh-stats", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
GET/api/v1/dashboard/projects/{project_id}/content/media

List Media

List media files for the current client, newest first.

Filters: folder (exact match), mime_type (prefix match — image/ catches all image MIME types).

Parameters

NameInTypeRequiredDescription
pagequeryintegerfalse
page_sizequeryintegerfalse
folderqueryanyfalse
mime_typequeryanyfalse
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media", {
  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/projects/{project_id}/content/media", 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/projects/{project_id}/content/media/upload

Upload Media

Upload an image to Cloudflare R2.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/upload' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "file": "string",
  "folder": "/",
  "alt_text": "string"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/upload",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"file": "string", "folder": "/", "alt_text": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/upload", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"file": "string", "folder": "/", "alt_text": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"file": "string", "folder": "/", "alt_text": "string"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/upload", 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
POST/api/v1/dashboard/projects/{project_id}/content/media/upload-from-url

Upload Media From Url

Host a remote image URL on Cloudflare R2 — the agent-callable, JSON-only twin of POST /media/upload.

Agents reaching the content platform via skill_call can't send multipart, and a generated hero image lives at a provider URL (kie.* etc.) that the cover_image_url allowlist rejects. This fetches the URL SSRF-safely and runs the same validate → WebP-transcode → R2 → content_media → catalog pipeline as /media/upload; the returned media.r2_url is on our allowlisted host, so it then passes straight into createPost / content_update_page with no allowlist change.

201 + {success, media, asset}. A bad/unreachable URL or non-image body is a 400; an oversized body (>5 MB) is a 413.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/upload-from-url' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "media_url": "string",
  "folder": "/",
  "alt_text": "string"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/upload-from-url",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"media_url": "string", "folder": "/", "alt_text": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/upload-from-url", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"media_url": "string", "folder": "/", "alt_text": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"media_url": "string", "folder": "/", "alt_text": "string"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/upload-from-url", 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
POST/api/v1/dashboard/projects/{project_id}/content/media/upload-batch

Upload Media Batch

Upload one or many files to SpiderMedia (SeaweedFS).

Weight policy — scroll-sequence folders (scroll-sequences/* or is_scroll_sequence=true): 500 KB per-file hard, 20 MB batch total hard, 200 KB / 10 MB soft warnings. Everything else: 20 MB per-file (500 MB for video/*), 500 MB batch total. Hard ceilings return 400 with the offending file(s); soft warnings come back in warnings[] with the upload succeeding.

Returns {uploaded: [...], failed: [...], warnings: [...], totals}.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/upload-batch' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "files": [
    "string"
  ],
  "folder": "string",
  "preserve_filename": false,
  "is_scroll_sequence": false
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/upload-batch",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"files": ["string"], "folder": "string", "preserve_filename": false, "is_scroll_sequence": false},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/upload-batch", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"files": ["string"], "folder": "string", "preserve_filename": false, "is_scroll_sequence": false})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"files": ["string"], "folder": "string", "preserve_filename": false, "is_scroll_sequence": false}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/upload-batch", 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
PATCH/api/v1/dashboard/projects/{project_id}/content/media/{media_id}

Update Media

Update a legacy R2 media file's metadata (folder / alt_text / caption).

Targets the content_media table (the dashboard R2 uploader surface), NOT the per-tenant media_assets catalog. True PATCH — only supplied fields change. 200 + the updated row; 404 if no such media for this client.

Parameters

NameInTypeRequiredDescription
media_idpathstringtrue
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/{media_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "folder": "string",
  "alt_text": "string",
  "caption": "string"
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/{media_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"folder": "string", "alt_text": "string", "caption": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/{media_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"folder": "string", "alt_text": "string", "caption": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"folder": "string", "alt_text": "string", "caption": "string"}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/{media_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/projects/{project_id}/content/media/{media_id}

Delete Media

Delete a legacy R2 media file (content_media row + best-effort R2 object cleanup). 204 on success, 404 if no such media for this client.

The DB row delete is authoritative; the R2 object removal is best-effort and non-blocking — an orphaned R2 object never fails the request (the row is already gone, so the asset no longer appears in the library).

Parameters

NameInTypeRequiredDescription
media_idpathstringtrue
Try it
Query

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/{media_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/{media_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/media/{media_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/projects/{project_id}/content/media/{media_id}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
204Successful Response
422Validation Error
GET/api/v1/dashboard/projects/{project_id}/content/settings

Get Settings

Get content settings.

Try it

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/settings' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/settings",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/settings", {
  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/projects/{project_id}/content/settings", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
PATCH/api/v1/dashboard/projects/{project_id}/content/settings

Update Settings

Update content settings. Phase 11+12 dry_run/confirm_token gated.

Parameters

NameInTypeRequiredDescription
dry_runquerybooleanfalsePhase 11+12: preview the change and receive a confirm_token without mutating.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and perform the update.
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/settings' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "site_name": "string",
  "site_tagline": "string",
  "favicon_url": "string",
  "primary_color": "string",
  "surface_color": "string",
  "surface_elevated_color": "string",
  "subtle_color": "string",
  "body_text_color": "string",
  "heading_color": "string",
  "logo_dark_url": "string",
  "logo_light_url": "string",
  "copyright_text": "string",
  "social_links": {},
  "google_analytics_id": "string",
  "plausible_domain": "string",
  "default_meta_title": "string",
  "default_meta_description": "string",
  "default_og_image_url": "string",
  "default_seo_title_suffix": "string",
  "default_agent_strategy": "string"
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/settings",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"site_name": "string", "site_tagline": "string", "favicon_url": "string", "primary_color": "string", "surface_color": "string", "surface_elevated_color": "string", "subtle_color": "string", "body_text_color": "string", "heading_color": "string", "logo_dark_url": "string", "logo_light_url": "string", "copyright_text": "string", "social_links": {}, "google_analytics_id": "string", "plausible_domain": "string", "default_meta_title": "string", "default_meta_description": "string", "default_og_image_url": "string", "default_seo_title_suffix": "string", "default_agent_strategy": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/settings", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"site_name": "string", "site_tagline": "string", "favicon_url": "string", "primary_color": "string", "surface_color": "string", "surface_elevated_color": "string", "subtle_color": "string", "body_text_color": "string", "heading_color": "string", "logo_dark_url": "string", "logo_light_url": "string", "copyright_text": "string", "social_links": {}, "google_analytics_id": "string", "plausible_domain": "string", "default_meta_title": "string", "default_meta_description": "string", "default_og_image_url": "string", "default_seo_title_suffix": "string", "default_agent_strategy": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"site_name": "string", "site_tagline": "string", "favicon_url": "string", "primary_color": "string", "surface_color": "string", "surface_elevated_color": "string", "subtle_color": "string", "body_text_color": "string", "heading_color": "string", "logo_dark_url": "string", "logo_light_url": "string", "copyright_text": "string", "social_links": {}, "google_analytics_id": "string", "plausible_domain": "string", "default_meta_title": "string", "default_meta_description": "string", "default_og_image_url": "string", "default_seo_title_suffix": "string", "default_agent_strategy": "string"}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/settings", 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/projects/{project_id}/content/redirects

List Redirects

List all redirects.

Try it

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/redirects' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/redirects",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/redirects", {
  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/projects/{project_id}/content/redirects", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
POST/api/v1/dashboard/projects/{project_id}/content/redirects

Create Redirect

Create a redirect.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/redirects' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "from_path": "string",
  "to_path": "string",
  "status_code": 301
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/redirects",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"from_path": "string", "to_path": "string", "status_code": 301},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/redirects", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"from_path": "string", "to_path": "string", "status_code": 301})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"from_path": "string", "to_path": "string", "status_code": 301}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/redirects", 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/projects/{project_id}/content/redirects/{redirect_id}

Delete Redirect

Delete a redirect.

Parameters

NameInTypeRequiredDescription
redirect_idpathstringtrue
Try it
Query

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/redirects/{redirect_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/redirects/{redirect_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/redirects/{redirect_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/projects/{project_id}/content/redirects/{redirect_id}", 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/projects/{project_id}/content/domains

List Domains

List all custom domains for this client plus the auto-provisioned platform preview URL when the client has ever deployed.

Try it

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains", {
  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/projects/{project_id}/content/domains", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
POST/api/v1/dashboard/projects/{project_id}/content/domains

Add Domain

Register a new custom domain.

Drives BOTH Cloudflare onboarding paths and surfaces the outcome of each so the dashboard can render an actionable banner instead of silently masking failures:

  • CF for SaaS custom hostname — for domains whose zone is NOT in our CF account. The client adds a CNAME to the fallback origin and CF handles SSL + dispatch.
  • Worker Route on the domain's own zone — for domains whose zone IS in our CF account (incl. subdomains of zones we own). Without this, KV mappings exist but CF returns 522 because no Worker handles the inbound request.

Each helper detects which path it owns and no-ops on the other (see register_custom_hostname skipping in-account zones, and ensure_worker_route skipping zones in other accounts). Both are called unconditionally; their structured return values populate worker_route_status and custom_hostname_status on the response.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "domain": "acme.com"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"domain": "acme.com"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"domain": "acme.com"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"domain": "acme.com"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains", 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/projects/{project_id}/content/domains/subdomain

Add Subdomain

Register a free {label}.sites.spideriq.ai subdomain.

The zero-cost counterpart to add_domain: sites.spideriq.ai is a zone we own with a wildcard Worker Route already configured, so this path makes NO Cloudflare custom-hostname call and needs NO DNS verification — it writes the DOMAIN_MAP KV entry and the dispatch Worker routes the hostname to the client's tenant script. Available on every tier; the free tier's single slot is one of these.

Counts against the same max_domains quota as a custom domain.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/subdomain' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "label": "acme"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/subdomain",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"label": "acme"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/subdomain", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"label": "acme"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"label": "acme"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/subdomain", 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/projects/{project_id}/content/domains/subdomain/availability

Check Subdomain Availability

Check whether a {label}.sites.spideriq.ai subdomain is free.

Powers the live availability check in the dashboard subdomain editor. Returns {available, host, reason}. available=false with a reason when the label is malformed; otherwise reflects global host uniqueness (content_domains.domain is globally unique).

Parameters

NameInTypeRequiredDescription
labelquerystringtrue
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/subdomain/availability' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/subdomain/availability",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/subdomain/availability", {
  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/projects/{project_id}/content/domains/subdomain/availability", 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/projects/{project_id}/content/domains/{domain}

Update Domain

Update a domain (SD1): set its start page and/or rename the host.

A rename remaps Cloudflare so the new host serves the same tenant site — the new DOMAIN_MAP KV entry (and, for an out-of-account custom domain, a fresh custom hostname + Worker Route) is created and the old host's mapping is torn down. Subdomains on *.sites.spideriq.ai route via the existing wildcard, so they only need the KV swap. The change goes live on the next deploy.

Parameters

NameInTypeRequiredDescription
domainpathstringtrue
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "homepage_slug": "promo",
  "new_domain": "go.acme.com"
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"homepage_slug": "promo", "new_domain": "go.acme.com"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"homepage_slug": "promo", "new_domain": "go.acme.com"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"homepage_slug": "promo", "new_domain": "go.acme.com"}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}", 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/projects/{project_id}/content/domains/{domain}

Remove Domain

Remove a custom domain.

Parameters

NameInTypeRequiredDescription
domainpathstringtrue
Try it
Query

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}", {
  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/projects/{project_id}/content/domains/{domain}", 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/projects/{project_id}/content/domains/{domain}/verify

Verify Domain

Verify a domain (checks DNS TXT record).

Surfaces needs_deploy=True when the client has no live deploy yet so the dashboard can prompt "Click to deploy your site" — without that, a freshly verified domain will return CF 522 because the per-client tenant Worker script doesn't exist in the dispatch namespace.

Parameters

NameInTypeRequiredDescription
domainpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}/verify' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}/verify",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}/verify", {
  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/projects/{project_id}/content/domains/{domain}/verify", 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/projects/{project_id}/content/domains/{domain}/recheck

Recheck Domain Ssl

Re-query Cloudflare for this domain's live SSL state and persist it.

The on-demand, customer-triggered counterpart to the background reconciliation poll: powers the dashboard "Re-check" button so a customer who just fixed their DNS doesn't have to wait for the next poll tick. Does exactly ONE Cloudflare custom-hostname read for the one domain (not a fan-out over the whole list — that stays cheap and rate-limit-safe), maps the CF SSL lifecycle onto our ssl_status enum, and returns the refreshed row with the live CF status echoed in custom_hostname_status.

Parameters

NameInTypeRequiredDescription
domainpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}/recheck' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}/recheck",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}/recheck", {
  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/projects/{project_id}/content/domains/{domain}/recheck", 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/projects/{project_id}/content/domains/{domain}/primary

Set Primary Domain

Set a domain as the primary domain for this client.

Parameters

NameInTypeRequiredDescription
domainpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}/primary' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}/primary",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}/primary", {
  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/projects/{project_id}/content/domains/{domain}/primary", 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/projects/{project_id}/content/domains/{domain}/reassign-project

Reassign Domain Project

Move a domain to a different project (website) in the same workspace.

Projects 4a migration helper: every existing domain was backfilled to the workspace DEFAULT project, so a multi-project workspace needs this to assign a domain to its real website (e.g. docs.example.com → the docs project). Workspace-scoped on purpose — the move targets a domain regardless of the currently-selected project, because the point is to move it OUT of its current one. The target project is validated to belong to this workspace.

Parameters

NameInTypeRequiredDescription
domainpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}/reassign-project' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "project_id": "proj_6c76213060eb"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}/reassign-project",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"project_id": "proj_6c76213060eb"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}/reassign-project", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"project_id": "proj_6c76213060eb"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"project_id": "proj_6c76213060eb"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/domains/{domain}/reassign-project", 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/projects/{project_id}/content/pages/{page_id}/reassign-project

Reassign Page Project

Move a page (and its folder subtree) to another project in this workspace.

Parameters

NameInTypeRequiredDescription
page_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/reassign-project' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "project_id": "proj_6c76213060eb"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/reassign-project",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"project_id": "proj_6c76213060eb"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/reassign-project", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"project_id": "proj_6c76213060eb"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"project_id": "proj_6c76213060eb"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/pages/{page_id}/reassign-project", 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/projects/{project_id}/content/posts/{post_id}/reassign-project

Reassign Post Project

Move a blog post to another project in this workspace (clears project-scoped categories/tags/relationships; free-text tags + pins ride along).

Parameters

NameInTypeRequiredDescription
post_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/reassign-project' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "project_id": "proj_6c76213060eb"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/reassign-project",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"project_id": "proj_6c76213060eb"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/reassign-project", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"project_id": "proj_6c76213060eb"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"project_id": "proj_6c76213060eb"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/posts/{post_id}/reassign-project", 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/projects/{project_id}/content/docs/{doc_id}/reassign-project

Reassign Doc Project

Move a doc (and its subtree) to another project in this workspace.

Parameters

NameInTypeRequiredDescription
doc_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/reassign-project' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "project_id": "proj_6c76213060eb"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/reassign-project",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"project_id": "proj_6c76213060eb"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/reassign-project", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"project_id": "proj_6c76213060eb"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"project_id": "proj_6c76213060eb"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/docs/{doc_id}/reassign-project", 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/projects/{project_id}/content/changelog/{entry_id}/reassign-project

Reassign Changelog Project

Move a changelog entry to another project in this workspace.

Parameters

NameInTypeRequiredDescription
entry_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}/reassign-project' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "project_id": "proj_6c76213060eb"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}/reassign-project",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"project_id": "proj_6c76213060eb"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}/reassign-project", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"project_id": "proj_6c76213060eb"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"project_id": "proj_6c76213060eb"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}/reassign-project", 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/projects/{project_id}/content/deploy

Deploy Site

Deploy the client's tenant site to Workers for Platforms.

Phase 11+12: pass dry_run=true to receive a preview URL and confirm_token without deploying; pass confirm_token=<cft_…> to consume the prior preview and deploy to production. Calls without either flag keep today's immediate behaviour (back-compat until Stage 4 rollout flips the default).

domain=<host> (Bug #4) scopes which of the workspace's domains get their CF DOMAIN_MAP entry + Worker Route refreshed, so a deploy no longer silently re-touches a sibling domain's routing. Unknown host → 400.

Parameters

NameInTypeRequiredDescription
dry_runquerybooleanfalsePhase 11+12: issue a preview + confirm_token without deploying.
confirm_tokenqueryanyfalsePhase 11+12: consume a prior preview token and deploy to production.
domainqueryanyfalseBug #4: scope the DOMAIN_MAP/route fan-out to a single host of this workspace (else all of the active project's domains).
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy", {
  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/projects/{project_id}/content/deploy", 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/projects/{project_id}/content/deploy/preview

Deploy Site Preview

Phase 11+12 Stage 2 — issue a preview URL + confirm_token for the proposed deploy. No CF production script upload, no DNS flip. Caller reviews the preview, then calls POST /deploy/production with the confirm_token to actually deploy.

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/preview' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/preview",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/preview", {
  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/projects/{project_id}/content/deploy/preview", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
POST/api/v1/dashboard/projects/{project_id}/content/deploy/production

Deploy Site Production

Phase 11+12 Stage 2 — consume a prior preview's confirm_token (Lock 4) and run the real deploy. 403 on tenant/action/resource mismatch, 410 on expired, 409 on already-consumed replay.

domain=<host> (Bug #4) scopes the routing fan-out to a single host.

Parameters

NameInTypeRequiredDescription
confirm_tokenquerystringtrueToken from a prior /deploy/preview call.
domainqueryanyfalseBug #4: scope the DOMAIN_MAP/route fan-out to a single host of this workspace (else all of the active project's domains).
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/production' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/production",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/production", {
  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/projects/{project_id}/content/deploy/production", 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/projects/{project_id}/content/deploy/status

Get Deploy Status

Get the most recent deploy status for this client.

Try it

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/status' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/status",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/status", {
  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/projects/{project_id}/content/deploy/status", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
GET/api/v1/dashboard/projects/{project_id}/content/deploy/history

List Deploys

List recent deploys for this client.

Parameters

NameInTypeRequiredDescription
limitqueryintegerfalse
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/history' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/history",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/history", {
  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/projects/{project_id}/content/deploy/history", 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/projects/{project_id}/content/deploy/readiness

Get Deploy Readiness

Check if this client's site is ready to deploy.

Returns a checklist of prerequisites (settings, domain, templates, pages) with pass/fail status and actionable fix instructions. Blocking items prevent deploy; warnings are advisory.

Try it

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/readiness' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/readiness",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/readiness", {
  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/projects/{project_id}/content/deploy/readiness", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response
GET/api/v1/dashboard/projects/{project_id}/content/deploy/{deploy_id}

Get Deploy Detail

Full detail for a single deploy — backs the per-deploy detail page.

Client-scoped: returns 404 if the deploy doesn't exist OR belongs to a different tenant (no cross-tenant leakage). Computes duration_ms from deployed_at − created_at. Declared AFTER the static /deploy/* routes so {deploy_id} never shadows status/history/readiness.

Parameters

NameInTypeRequiredDescription
deploy_idpathstringtrue
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/{deploy_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/{deploy_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/deploy/{deploy_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/projects/{project_id}/content/deploy/{deploy_id}", 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/projects/{project_id}/content/changelog

List Changelog

List changelog entries (newest first).

Drafts are included for the editor surface. Paginated — the public feed + timeline read the same service method with include_drafts=False.

Parameters

NameInTypeRequiredDescription
statusqueryanyfalseFilter by status (draft / published / archived).
pagequeryanyfalse1-based page number (house pattern; wins over limit/offset).
page_sizequeryanyfalseEntries per page (1-200, default 50).
limitqueryanyfalseLegacy alias for page_size. Kept for back-compat.
offsetqueryanyfalseLegacy alias — raw row offset. Kept for back-compat.
sortquerystringfalseOrdering, newest first. published_at (default) = release date. version = semver compared NUMERICALLY per component, so v2.10.0 sorts above v2.9.0 — use it when the entries were backfilled and their timestamps don't reflect true release order.
include_bodyquerybooleanfalseInclude each entry's full Tiptap body. Pass false for a light index (id/version/title/status/dates) — 25 entries with bodies is ~128k chars, which blows an agent's tool-output ceiling. Fetch a single body with GET /changelog/{entry_id}. Defaults true so the dashboard editor keeps its one-shot list→edit flow.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog", {
  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/projects/{project_id}/content/changelog", 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/projects/{project_id}/content/changelog

Create Changelog

Create a draft changelog entry (409 on a duplicate version).

published_at is optional and does NOT publish the entry — it pre-stamps the release date so a backfilled history lands in true order on the public timeline (which is ordered by date, never by version string).

Try it

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "version": "string",
  "title": "string",
  "body": {},
  "published_at": "2026-01-01T00:00:00Z"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"version": "string", "title": "string", "body": {}, "published_at": "2026-01-01T00:00:00Z"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"version": "string", "title": "string", "body": {}, "published_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(`{"version": "string", "title": "string", "body": {}, "published_at": "2026-01-01T00:00:00Z"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog", 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/projects/{project_id}/content/changelog/{entry_id}

Get Changelog

Get one changelog entry by ID (drafts included).

Parameters

NameInTypeRequiredDescription
entry_idpathstringtrue
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_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/projects/{project_id}/content/changelog/{entry_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/projects/{project_id}/content/changelog/{entry_id}

Update Changelog

Update a changelog entry's title/body (version is immutable post-create only via this route's schema; pass it through update_changelog if needed).

Parameters

NameInTypeRequiredDescription
entry_idpathstringtrue
Try it
Query

Examples

cURL
curl -X PATCH 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "version": "string",
  "title": "string",
  "body": {},
  "published_at": "2026-01-01T00:00:00Z"
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"version": "string", "title": "string", "body": {}, "published_at": "2026-01-01T00:00:00Z"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"version": "string", "title": "string", "body": {}, "published_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(`{"version": "string", "title": "string", "body": {}, "published_at": "2026-01-01T00:00:00Z"}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_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/projects/{project_id}/content/changelog/{entry_id}

Delete Changelog

Soft-delete a changelog entry (status → archived). Returns 204.

Parameters

NameInTypeRequiredDescription
entry_idpathstringtrue
Try it
Query

Examples

cURL
curl -X DELETE 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_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/projects/{project_id}/content/changelog/{entry_id}", 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/projects/{project_id}/content/changelog/{entry_id}/publish

Publish Changelog

Publish a changelog entry (fires changelog.published on first publish).

The body is OPTIONAL — with none, the entry is stamped NOW() exactly as before. Send {"published_at": "..."} to publish a historical entry with its real release date; it wins over any date already on the entry.

Parameters

NameInTypeRequiredDescription
entry_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}/publish' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "published_at": "2026-01-01T00:00:00Z"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}/publish",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"published_at": "2026-01-01T00:00:00Z"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}/publish", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"published_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(`{"published_at": "2026-01-01T00:00:00Z"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}/publish", 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/projects/{project_id}/content/changelog/{entry_id}/unpublish

Unpublish Changelog

Revert a changelog entry to draft.

Parameters

NameInTypeRequiredDescription
entry_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}/unpublish' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}/unpublish",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/changelog/{entry_id}/unpublish", {
  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/projects/{project_id}/content/changelog/{entry_id}/unpublish", 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/projects/{project_id}/content/audit/links

Audit Internal Links

Walk every published page's blocks + navigation menus and validate internal links against the published-page roster + active redirects.

Returns {valid_count, broken: [{path, source, reason}], proposed_redirects, known_redirects}.

Fixes the Unavis-report pain: cleaning up /en/* legacy URLs across nav + blocks used to require manual crawling. One call surfaces every broken link with its exact source so agents can propose redirects in a single pass.

Try it

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/audit/links' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/audit/links",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/audit/links", {
  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/projects/{project_id}/content/audit/links", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}

Responses

StatusDescription
200Successful Response