SSpiderIQ
SSpiderIQ

Docs / api-reference/content-studio-components

Content Studio - Components

30 endpoints from the published OpenAPI import.

GET/api/v1/dashboard/content/components

List Components

List components for the current client. Supports filtering by category, marketplace_category, status, and the universal browse-by-intent axes (mood / palette / brand_fit / scene_type) plus agent_meta role/surface.

Audit nav-shell page-07 Q4 (2026-05-05): super_admin can call this without selecting a tenant scope — the dependency returns user.client_id=None, and the service treats None as "admin view" (no client_id filter, returns global rows + every per-tenant copy across all clients).

CRO bug-fix bundle (2026-05-08, Antigravity report Bug 3): the service layer has supported marketplace_category filtering since Phase A, but the API layer wasn't forwarding the query param — ?marketplace_category=... was silently ignored. Agent Embed M3 (2026-06-27) extends the same wiring to the universal axes + agent_meta role/surface so agents are browsable by intent.

Parameters

NameInTypeRequiredDescription
categoryqueryanyfalseFilter by category
marketplace_categoryqueryanyfalseFilter by marketplace_category (e.g. 'urgency-scarcity', 'capture-popups', 'social-proof', 'agent')
statusqueryanyfalseFilter by status (draft/published/archived)
include_globalquerybooleanfalseInclude system (global) components
moodqueryanyfalseUniversal mood axis — repeatable (?mood=calm&mood=warm). OR-match (overlap).
palettequeryanyfalseUniversal palette axis — repeatable. OR-match (overlap).
brand_fitqueryanyfalseUniversal brand-fit/industry axis — repeatable (?brand_fit=wellness). OR-match.
scene_typequeryanyfalseUniversal scene_type axis — single value, equality.
agent_rolequeryanyfalseagent_meta.role for marketplace_category='agent' listings (sdr|support|concierge|booking).
agent_surfacequeryanyfalseagent_meta.surface for agent listings (flow|inline|concierge).
agent_form_factorqueryanyfalseagent_meta.form_factor mount taxonomy for agent listings (section|widget|concierge|headless).
pagequeryintegerfalse
page_sizequeryintegerfalse
Try it
Query

Examples

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

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

Create Component

Create a new UI component. 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/components' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "slug": "string",
  "name": "string",
  "description": "string",
  "version": "1.0.0",
  "category": "custom",
  "html_template": "string",
  "css": "string",
  "js": "string",
  "dependencies": [
    "string"
  ],
  "props_schema": {},
  "default_props": {},
  "thumbnail_url": "string",
  "tags": [
    "string"
  ],
  "is_global": false,
  "framework": "string",
  "source_code": "string",
  "auto_extract_css": false,
  "preview_thumbnail_url": "string",
  "replication_prompt": "string",
  "marketplace_category": "string"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/components",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"slug": "string", "name": "string", "description": "string", "version": "1.0.0", "category": "custom", "html_template": "string", "css": "string", "js": "string", "dependencies": ["string"], "props_schema": {}, "default_props": {}, "thumbnail_url": "string", "tags": ["string"], "is_global": false, "framework": "string", "source_code": "string", "auto_extract_css": false, "preview_thumbnail_url": "string", "replication_prompt": "string", "marketplace_category": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/components", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"slug": "string", "name": "string", "description": "string", "version": "1.0.0", "category": "custom", "html_template": "string", "css": "string", "js": "string", "dependencies": ["string"], "props_schema": {}, "default_props": {}, "thumbnail_url": "string", "tags": ["string"], "is_global": false, "framework": "string", "source_code": "string", "auto_extract_css": false, "preview_thumbnail_url": "string", "replication_prompt": "string", "marketplace_category": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"slug": "string", "name": "string", "description": "string", "version": "1.0.0", "category": "custom", "html_template": "string", "css": "string", "js": "string", "dependencies": ["string"], "props_schema": {}, "default_props": {}, "thumbnail_url": "string", "tags": ["string"], "is_global": false, "framework": "string", "source_code": "string", "auto_extract_css": false, "preview_thumbnail_url": "string", "replication_prompt": "string", "marketplace_category": "string"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/components", 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/components/by-slug/{slug}

Get Component By Slug

Get a component by slug. Returns latest published version if no version specified.

Parameters

NameInTypeRequiredDescription
slugpathstringtrue
versionqueryanyfalseSpecific version (default: latest)
Try it
Query

Examples

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

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

Get Component

Get a component by ID.

Parameters

NameInTypeRequiredDescription
component_idpathstringtrue
Try it
Query

Examples

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

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

Update Component

Update a component. Only provided fields are changed. Phase 11+12 dry_run/confirm_token gated.

Unknown fields in the request body are ignored (Pydantic default) but surfaced in the response's warnings array with a "Did you mean X?" hint when a close field name exists. This catches css_styles (should be css) silent-drops.

Phase E (2026-05-05) — accepts Phase A 4-class taxonomy (kind, block_type, js_runtime, layouts, sources, extension_spec) + agent-discovery axes (mood, palette, brand_fit_tags, scene_type, agent_meta). Strict enum validation at the boundary; cross-field invariants are backstopped by DB CHECK constraints (migration 174).

Parameters

NameInTypeRequiredDescription
component_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/components/{component_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "description": "string",
  "category": "hero",
  "html_template": "string",
  "css": "string",
  "js": "string",
  "dependencies": [
    "string"
  ],
  "props_schema": {},
  "default_props": {},
  "thumbnail_url": "string",
  "tags": [
    "string"
  ],
  "framework": "string",
  "source_code": "string",
  "auto_extract_css": false,
  "preview_thumbnail_url": "string",
  "replication_prompt": "string",
  "marketplace_category": "string",
  "marketplace_featured": true,
  "marketplace_description": "string",
  "kind": "static"
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/content/components/{component_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "description": "string", "category": "hero", "html_template": "string", "css": "string", "js": "string", "dependencies": ["string"], "props_schema": {}, "default_props": {}, "thumbnail_url": "string", "tags": ["string"], "framework": "string", "source_code": "string", "auto_extract_css": false, "preview_thumbnail_url": "string", "replication_prompt": "string", "marketplace_category": "string", "marketplace_featured": true, "marketplace_description": "string", "kind": "static"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/components/{component_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "description": "string", "category": "hero", "html_template": "string", "css": "string", "js": "string", "dependencies": ["string"], "props_schema": {}, "default_props": {}, "thumbnail_url": "string", "tags": ["string"], "framework": "string", "source_code": "string", "auto_extract_css": false, "preview_thumbnail_url": "string", "replication_prompt": "string", "marketplace_category": "string", "marketplace_featured": true, "marketplace_description": "string", "kind": "static"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "description": "string", "category": "hero", "html_template": "string", "css": "string", "js": "string", "dependencies": ["string"], "props_schema": {}, "default_props": {}, "thumbnail_url": "string", "tags": ["string"], "framework": "string", "source_code": "string", "auto_extract_css": false, "preview_thumbnail_url": "string", "replication_prompt": "string", "marketplace_category": "string", "marketplace_featured": true, "marketplace_description": "string", "kind": "static"}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/content/components/{component_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
400DB CHECK constraint violation (e.g. PATCH leaves row with kind='dynamic' but block_type=NULL — Phase A invariant in migration 174).
403Cannot edit a global component you don't own; or confirm_token mismatch (Phase 11+12).
404Component not found.
409confirm_token already consumed (Phase 11+12).
410confirm_token expired (Phase 11+12).
422Body failed validation: unknown enum (kind/block_type/js_runtime/scene_type/mood/brand_fit_tag), agent_meta with unknown key (extra='forbid'), invalid Literal (interaction_pattern, trigger_kind), or layouts/sources length cap.
DELETE/api/v1/dashboard/content/components/{component_id}

Delete Component

Delete a component. Only the owning client can delete (not global components). Phase 11+12 gated.

Parameters

NameInTypeRequiredDescription
component_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/components/{component_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

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

Preview Component

Render a single component in isolation for dashboard iframe preview.

Closes the BrokerZ-report pain: Shadow DOM layout issues were only visible after a full site preview deploy (~60-90 seconds). This endpoint returns the component's html_template + css + js + merged props so the dashboard can iframe-srcdoc it instantly for quick styling checks.

Note: v1 returns the raw html_template — Liquid {{ props.x }} tokens are NOT interpolated here (the Liquid runtime lives in the Worker bundle). The response exposes merged_props so the dashboard's own renderer can interpolate client-side if needed. Full-fidelity preview still ships via the existing /deploy/preview flow.

Parameters

NameInTypeRequiredDescription
component_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/components/{component_id}/preview' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "props": {},
  "viewport": "desktop"
}'
Python
import httpx

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

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"props": {}, "viewport": "desktop"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/components/{component_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/components/{component_id}/upload-preview

Upload Component Preview

Upload a preview image (PNG/JPG/GIF/WEBP/MP4) for a component to R2 at components/<slug>.<ext>, then PATCH preview_thumbnail_url on the row.

Single round-trip — the editor doesn't need a separate PATCH after upload.

Phase E (2026-05-05) — Content-Type and magic-number are now validated alongside the extension. Capped at 5 MB; for larger assets, use the SpiderMedia /files/upload endpoint and reference the URL via PATCH.

Parameters

NameInTypeRequiredDescription
component_idpathstringtrue
Try it
Query

Examples

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

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

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"ext": "string", "file": "string"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/components/{component_id}/upload-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
413Upload exceeds 5 MB size limit. Use SpiderMedia for larger assets.
415Unsupported extension, Content-Type/extension mismatch, or magic-number mismatch.
422Validation Error
POST/api/v1/dashboard/content/components/{component_id}/publish

Publish Component

Publish a component (makes it available for rendering on live sites). For framework components (Tier 4), returns 202 — build runs async. Phase 11+12 gated.

Parameters

NameInTypeRequiredDescription
component_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the publish 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/components/{component_id}/publish' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/components/{component_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/components/{component_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/components/{component_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/components/{component_id}/archive

Archive Component

Archive a component (removes from rendering but preserves data). Phase 11+12 gated.

Parameters

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

Examples

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

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

Get Build Status

Get the build status of a framework component (Tier 4).

Parameters

NameInTypeRequiredDescription
component_idpathstringtrue
Try it
Query

Examples

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

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

Rebuild Component

Trigger a rebuild for a framework component (Tier 4). Returns 202.

Parameters

NameInTypeRequiredDescription
component_idpathstringtrue
Try it
Query

Examples

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

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

List Component Versions

List all versions of a component by slug.

Parameters

NameInTypeRequiredDescription
slugpathstringtrue
Try it
Query

Examples

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

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

Component Rollback

Restore a component to an earlier version by creating a new published version with the target version's content, and repointing consuming pages.

One confirm_token covers the whole rollback. Gate action is component_rollback (distinct from component_update_and_propagate), so a forward-update token can't accidentally be consumed against this path.

Never auto-deploys the tenant KV. Block-level updates render live on next request.

Parameters

NameInTypeRequiredDescription
slugpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/components/{slug}/rollback' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "target_version": "string",
  "bump": "patch",
  "pages": [
    "string"
  ],
  "dry_run": false,
  "confirm_token": "string"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/components/{slug}/rollback",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"target_version": "string", "bump": "patch", "pages": ["string"], "dry_run": false, "confirm_token": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/components/{slug}/rollback", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"target_version": "string", "bump": "patch", "pages": ["string"], "dry_run": false, "confirm_token": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"target_version": "string", "bump": "patch", "pages": ["string"], "dry_run": false, "confirm_token": "string"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/components/{slug}/rollback", 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/components/{slug}/update-and-propagate

Component Update And Propagate

One-shot: bump a component to a new version AND propagate the pin to every (or selected) consuming page, gated by a single confirm_token.

Replaces the 5-step agent choreography (PATCH component → iterate pages → update block versions → publish each → deploy) with one call.

Never auto-deploys. The new component version is published and each affected page's blocks are updated in-place; block-level content renders live via the content API on next request. If you also changed templates or theme, run deploy_site_previewdeploy_site_production as usual.

Phase 11+12 Lock 4. A single confirm_token covers the whole composite mutation (component + all affected pages). Issue with dry_run=true, inspect the affected_pages preview, then send the token back on the real call.

Parameters

NameInTypeRequiredDescription
slugpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/content/components/{slug}/update-and-propagate' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "html_template": "string",
  "css": "string",
  "js": "string",
  "props_schema": {},
  "default_props": {},
  "dependencies": [
    "string"
  ],
  "name": "string",
  "description": "string",
  "bump": "patch",
  "pages": [
    "string"
  ],
  "dry_run": false,
  "confirm_token": "string"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/content/components/{slug}/update-and-propagate",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"html_template": "string", "css": "string", "js": "string", "props_schema": {}, "default_props": {}, "dependencies": ["string"], "name": "string", "description": "string", "bump": "patch", "pages": ["string"], "dry_run": false, "confirm_token": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/content/components/{slug}/update-and-propagate", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"html_template": "string", "css": "string", "js": "string", "props_schema": {}, "default_props": {}, "dependencies": ["string"], "name": "string", "description": "string", "bump": "patch", "pages": ["string"], "dry_run": false, "confirm_token": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"html_template": "string", "css": "string", "js": "string", "props_schema": {}, "default_props": {}, "dependencies": ["string"], "name": "string", "description": "string", "bump": "patch", "pages": ["string"], "dry_run": false, "confirm_token": "string"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/content/components/{slug}/update-and-propagate", 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/components

List Components

List components for the current client. Supports filtering by category, marketplace_category, status, and the universal browse-by-intent axes (mood / palette / brand_fit / scene_type) plus agent_meta role/surface.

Audit nav-shell page-07 Q4 (2026-05-05): super_admin can call this without selecting a tenant scope — the dependency returns user.client_id=None, and the service treats None as "admin view" (no client_id filter, returns global rows + every per-tenant copy across all clients).

CRO bug-fix bundle (2026-05-08, Antigravity report Bug 3): the service layer has supported marketplace_category filtering since Phase A, but the API layer wasn't forwarding the query param — ?marketplace_category=... was silently ignored. Agent Embed M3 (2026-06-27) extends the same wiring to the universal axes + agent_meta role/surface so agents are browsable by intent.

Parameters

NameInTypeRequiredDescription
categoryqueryanyfalseFilter by category
marketplace_categoryqueryanyfalseFilter by marketplace_category (e.g. 'urgency-scarcity', 'capture-popups', 'social-proof', 'agent')
statusqueryanyfalseFilter by status (draft/published/archived)
include_globalquerybooleanfalseInclude system (global) components
moodqueryanyfalseUniversal mood axis — repeatable (?mood=calm&mood=warm). OR-match (overlap).
palettequeryanyfalseUniversal palette axis — repeatable. OR-match (overlap).
brand_fitqueryanyfalseUniversal brand-fit/industry axis — repeatable (?brand_fit=wellness). OR-match.
scene_typequeryanyfalseUniversal scene_type axis — single value, equality.
agent_rolequeryanyfalseagent_meta.role for marketplace_category='agent' listings (sdr|support|concierge|booking).
agent_surfacequeryanyfalseagent_meta.surface for agent listings (flow|inline|concierge).
agent_form_factorqueryanyfalseagent_meta.form_factor mount taxonomy for agent listings (section|widget|concierge|headless).
pagequeryintegerfalse
page_sizequeryintegerfalse
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components",
    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/components", {
  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/components", 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/components

Create Component

Create a new UI component. 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/components' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "slug": "string",
  "name": "string",
  "description": "string",
  "version": "1.0.0",
  "category": "custom",
  "html_template": "string",
  "css": "string",
  "js": "string",
  "dependencies": [
    "string"
  ],
  "props_schema": {},
  "default_props": {},
  "thumbnail_url": "string",
  "tags": [
    "string"
  ],
  "is_global": false,
  "framework": "string",
  "source_code": "string",
  "auto_extract_css": false,
  "preview_thumbnail_url": "string",
  "replication_prompt": "string",
  "marketplace_category": "string"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"slug": "string", "name": "string", "description": "string", "version": "1.0.0", "category": "custom", "html_template": "string", "css": "string", "js": "string", "dependencies": ["string"], "props_schema": {}, "default_props": {}, "thumbnail_url": "string", "tags": ["string"], "is_global": false, "framework": "string", "source_code": "string", "auto_extract_css": false, "preview_thumbnail_url": "string", "replication_prompt": "string", "marketplace_category": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"slug": "string", "name": "string", "description": "string", "version": "1.0.0", "category": "custom", "html_template": "string", "css": "string", "js": "string", "dependencies": ["string"], "props_schema": {}, "default_props": {}, "thumbnail_url": "string", "tags": ["string"], "is_global": false, "framework": "string", "source_code": "string", "auto_extract_css": false, "preview_thumbnail_url": "string", "replication_prompt": "string", "marketplace_category": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"slug": "string", "name": "string", "description": "string", "version": "1.0.0", "category": "custom", "html_template": "string", "css": "string", "js": "string", "dependencies": ["string"], "props_schema": {}, "default_props": {}, "thumbnail_url": "string", "tags": ["string"], "is_global": false, "framework": "string", "source_code": "string", "auto_extract_css": false, "preview_thumbnail_url": "string", "replication_prompt": "string", "marketplace_category": "string"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components", 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/components/by-slug/{slug}

Get Component By Slug

Get a component by slug. Returns latest published version if no version specified.

Parameters

NameInTypeRequiredDescription
slugpathstringtrue
versionqueryanyfalseSpecific version (default: latest)
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/by-slug/{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/components/by-slug/{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/components/by-slug/{slug}", 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/components/{component_id}

Get Component

Get a component by ID.

Parameters

NameInTypeRequiredDescription
component_idpathstringtrue
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{component_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/components/{component_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/components/{component_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/components/{component_id}

Update Component

Update a component. Only provided fields are changed. Phase 11+12 dry_run/confirm_token gated.

Unknown fields in the request body are ignored (Pydantic default) but surfaced in the response's warnings array with a "Did you mean X?" hint when a close field name exists. This catches css_styles (should be css) silent-drops.

Phase E (2026-05-05) — accepts Phase A 4-class taxonomy (kind, block_type, js_runtime, layouts, sources, extension_spec) + agent-discovery axes (mood, palette, brand_fit_tags, scene_type, agent_meta). Strict enum validation at the boundary; cross-field invariants are backstopped by DB CHECK constraints (migration 174).

Parameters

NameInTypeRequiredDescription
component_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/components/{component_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "description": "string",
  "category": "hero",
  "html_template": "string",
  "css": "string",
  "js": "string",
  "dependencies": [
    "string"
  ],
  "props_schema": {},
  "default_props": {},
  "thumbnail_url": "string",
  "tags": [
    "string"
  ],
  "framework": "string",
  "source_code": "string",
  "auto_extract_css": false,
  "preview_thumbnail_url": "string",
  "replication_prompt": "string",
  "marketplace_category": "string",
  "marketplace_featured": true,
  "marketplace_description": "string",
  "kind": "static"
}'
Python
import httpx

resp = httpx.patch(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{component_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "description": "string", "category": "hero", "html_template": "string", "css": "string", "js": "string", "dependencies": ["string"], "props_schema": {}, "default_props": {}, "thumbnail_url": "string", "tags": ["string"], "framework": "string", "source_code": "string", "auto_extract_css": false, "preview_thumbnail_url": "string", "replication_prompt": "string", "marketplace_category": "string", "marketplace_featured": true, "marketplace_description": "string", "kind": "static"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{component_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "description": "string", "category": "hero", "html_template": "string", "css": "string", "js": "string", "dependencies": ["string"], "props_schema": {}, "default_props": {}, "thumbnail_url": "string", "tags": ["string"], "framework": "string", "source_code": "string", "auto_extract_css": false, "preview_thumbnail_url": "string", "replication_prompt": "string", "marketplace_category": "string", "marketplace_featured": true, "marketplace_description": "string", "kind": "static"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "description": "string", "category": "hero", "html_template": "string", "css": "string", "js": "string", "dependencies": ["string"], "props_schema": {}, "default_props": {}, "thumbnail_url": "string", "tags": ["string"], "framework": "string", "source_code": "string", "auto_extract_css": false, "preview_thumbnail_url": "string", "replication_prompt": "string", "marketplace_category": "string", "marketplace_featured": true, "marketplace_description": "string", "kind": "static"}`)
	req, _ := http.NewRequest("PATCH", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{component_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
400DB CHECK constraint violation (e.g. PATCH leaves row with kind='dynamic' but block_type=NULL — Phase A invariant in migration 174).
403Cannot edit a global component you don't own; or confirm_token mismatch (Phase 11+12).
404Component not found.
409confirm_token already consumed (Phase 11+12).
410confirm_token expired (Phase 11+12).
422Body failed validation: unknown enum (kind/block_type/js_runtime/scene_type/mood/brand_fit_tag), agent_meta with unknown key (extra='forbid'), invalid Literal (interaction_pattern, trigger_kind), or layouts/sources length cap.
DELETE/api/v1/dashboard/projects/{project_id}/content/components/{component_id}

Delete Component

Delete a component. Only the owning client can delete (not global components). Phase 11+12 gated.

Parameters

NameInTypeRequiredDescription
component_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/components/{component_id}' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.delete(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{component_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/components/{component_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/components/{component_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/components/{component_id}/preview

Preview Component

Render a single component in isolation for dashboard iframe preview.

Closes the BrokerZ-report pain: Shadow DOM layout issues were only visible after a full site preview deploy (~60-90 seconds). This endpoint returns the component's html_template + css + js + merged props so the dashboard can iframe-srcdoc it instantly for quick styling checks.

Note: v1 returns the raw html_template — Liquid {{ props.x }} tokens are NOT interpolated here (the Liquid runtime lives in the Worker bundle). The response exposes merged_props so the dashboard's own renderer can interpolate client-side if needed. Full-fidelity preview still ships via the existing /deploy/preview flow.

Parameters

NameInTypeRequiredDescription
component_idpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{component_id}/preview' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "props": {},
  "viewport": "desktop"
}'
Python
import httpx

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

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"props": {}, "viewport": "desktop"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{component_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/components/{component_id}/upload-preview

Upload Component Preview

Upload a preview image (PNG/JPG/GIF/WEBP/MP4) for a component to R2 at components/<slug>.<ext>, then PATCH preview_thumbnail_url on the row.

Single round-trip — the editor doesn't need a separate PATCH after upload.

Phase E (2026-05-05) — Content-Type and magic-number are now validated alongside the extension. Capped at 5 MB; for larger assets, use the SpiderMedia /files/upload endpoint and reference the URL via PATCH.

Parameters

NameInTypeRequiredDescription
component_idpathstringtrue
Try it
Query

Examples

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

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

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"ext": "string", "file": "string"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{component_id}/upload-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
413Upload exceeds 5 MB size limit. Use SpiderMedia for larger assets.
415Unsupported extension, Content-Type/extension mismatch, or magic-number mismatch.
422Validation Error
POST/api/v1/dashboard/projects/{project_id}/content/components/{component_id}/publish

Publish Component

Publish a component (makes it available for rendering on live sites). For framework components (Tier 4), returns 202 — build runs async. Phase 11+12 gated.

Parameters

NameInTypeRequiredDescription
component_idpathstringtrue
dry_runquerybooleanfalsePhase 11+12: preview the publish 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/components/{component_id}/publish' \
  -H 'Authorization: Bearer <token>'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{component_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/components/{component_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/components/{component_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/components/{component_id}/archive

Archive Component

Archive a component (removes from rendering but preserves data). Phase 11+12 gated.

Parameters

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

Examples

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

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{component_id}/archive",
    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/components/{component_id}/archive", {
  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/components/{component_id}/archive", 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/components/{component_id}/build-status

Get Build Status

Get the build status of a framework component (Tier 4).

Parameters

NameInTypeRequiredDescription
component_idpathstringtrue
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{component_id}/build-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/components/{component_id}/build-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/components/{component_id}/build-status", 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/components/{component_id}/rebuild

Rebuild Component

Trigger a rebuild for a framework component (Tier 4). Returns 202.

Parameters

NameInTypeRequiredDescription
component_idpathstringtrue
Try it
Query

Examples

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

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{component_id}/rebuild",
    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/components/{component_id}/rebuild", {
  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/components/{component_id}/rebuild", 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/components/{slug}/versions

List Component Versions

List all versions of a component by slug.

Parameters

NameInTypeRequiredDescription
slugpathstringtrue
Try it
Query

Examples

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

resp = httpx.get(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{slug}/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/components/{slug}/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/components/{slug}/versions", 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/components/{slug}/rollback

Component Rollback

Restore a component to an earlier version by creating a new published version with the target version's content, and repointing consuming pages.

One confirm_token covers the whole rollback. Gate action is component_rollback (distinct from component_update_and_propagate), so a forward-update token can't accidentally be consumed against this path.

Never auto-deploys the tenant KV. Block-level updates render live on next request.

Parameters

NameInTypeRequiredDescription
slugpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{slug}/rollback' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "target_version": "string",
  "bump": "patch",
  "pages": [
    "string"
  ],
  "dry_run": false,
  "confirm_token": "string"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{slug}/rollback",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"target_version": "string", "bump": "patch", "pages": ["string"], "dry_run": false, "confirm_token": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{slug}/rollback", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"target_version": "string", "bump": "patch", "pages": ["string"], "dry_run": false, "confirm_token": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"target_version": "string", "bump": "patch", "pages": ["string"], "dry_run": false, "confirm_token": "string"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{slug}/rollback", 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/components/{slug}/update-and-propagate

Component Update And Propagate

One-shot: bump a component to a new version AND propagate the pin to every (or selected) consuming page, gated by a single confirm_token.

Replaces the 5-step agent choreography (PATCH component → iterate pages → update block versions → publish each → deploy) with one call.

Never auto-deploys. The new component version is published and each affected page's blocks are updated in-place; block-level content renders live via the content API on next request. If you also changed templates or theme, run deploy_site_previewdeploy_site_production as usual.

Phase 11+12 Lock 4. A single confirm_token covers the whole composite mutation (component + all affected pages). Issue with dry_run=true, inspect the affected_pages preview, then send the token back on the real call.

Parameters

NameInTypeRequiredDescription
slugpathstringtrue
Try it
Query

Examples

cURL
curl -X POST 'https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{slug}/update-and-propagate' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "html_template": "string",
  "css": "string",
  "js": "string",
  "props_schema": {},
  "default_props": {},
  "dependencies": [
    "string"
  ],
  "name": "string",
  "description": "string",
  "bump": "patch",
  "pages": [
    "string"
  ],
  "dry_run": false,
  "confirm_token": "string"
}'
Python
import httpx

resp = httpx.post(
    "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{slug}/update-and-propagate",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"html_template": "string", "css": "string", "js": "string", "props_schema": {}, "default_props": {}, "dependencies": ["string"], "name": "string", "description": "string", "bump": "patch", "pages": ["string"], "dry_run": false, "confirm_token": "string"},
)
resp.raise_for_status()
print(resp.json())
JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{slug}/update-and-propagate", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"html_template": "string", "css": "string", "js": "string", "props_schema": {}, "default_props": {}, "dependencies": ["string"], "name": "string", "description": "string", "bump": "patch", "pages": ["string"], "dry_run": false, "confirm_token": "string"})
});
const data = await resp.json();
console.log(data);
Go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"html_template": "string", "css": "string", "js": "string", "props_schema": {}, "default_props": {}, "dependencies": ["string"], "name": "string", "description": "string", "bump": "patch", "pages": ["string"], "dry_run": false, "confirm_token": "string"}`)
	req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/dashboard/projects/{project_id}/content/components/{slug}/update-and-propagate", 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