Content
94 endpoints from the published OpenAPI import.
Content Help
AI agent reference: returns all available content types, block types, Liquid filters, tags, theme structure, and data sources.
Defaults to YAML (token-efficient). Use ?format=json for programmatic use. No authentication required.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/help' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/help",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/help", {
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/content/help", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Content Block Fields
E.2 (2026-05-22 Claude Code usability F-16) — per-block-type field map.
Returns:
- All block types when
block_typeis unset - The single block-type entry when
block_type=hero(or similar)
The shape mirrors the block_types section of /content/help, including:
fields: canonical fields the default theme's snippet reads_aliases: agent-natural mistakes → canonical replacement_anti_patterns: shapes that 422 with a hint_notes: free-form caveats
The source of truth is mirrored in:
- app/api/v1/_content_help.py (this endpoint's data)
- app/services/page_auditor.py (the audit warning + alias detection)
Both must stay in lock-step. Drift surfaces as silent-blank-section failures the auditor catches at read-time — and as wrong-hint advice here. Update both in the same PR.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
block_type | query | any | false | If set, return only the entry for this block_type. Omit to list all. |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/help/block-fields' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/help/block-fields",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/help/block-fields", {
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/content/help/block-fields", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Content Variables
AI agent merge-tag reference: every flat variable ({{ firstname }}, {{ company_name }}, {{ city }}, etc.) available in dynamic-landing templates, with descriptions, source paths, selection rules, and realistic example values from the Mario's Pizzeria demo fixture.
Auto-generated from apps/liquid-renderer/merge-tags.spec.json — the exact same JSON the TypeScript renderer imports at build time. Impossible to drift.
Defaults to YAML (token-efficient for agents). Use ?format=json for programmatic consumption. No authentication required.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/variables' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/variables",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/variables", {
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/content/variables", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
List Themes
List available built-in themes (public, no auth).
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/themes' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/themes",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/themes", {
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/content/themes", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Get Theme Detail
Get a theme's details and all template files (public, no auth).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | path | string | true |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/themes/{name}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/themes/{name}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/themes/{name}", {
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/content/themes/{name}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Browse public site templates
List public site templates. No auth — anyone can browse the gallery. Phase D adds 5 universal-axis filters (mood, palette, brand_fit, scene_type, agent_meta.<key>). The /marketplace/site-templates path is an alias for the same endpoint.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
industry | query | any | false | |
use_case | query | any | false | |
tag | query | any | false | Filter to templates that have this tag |
is_featured | query | any | false | |
is_single_page | query | any | false | true = single-page templates (opt-in/thankyou/VSL); false = whole-site templates; omit = both. |
mood | query | array[string] | false | Multi-value mood filter (set-overlap). |
palette | query | array[string] | false | Multi-value palette filter (set-overlap). |
brand_fit | query | array[string] | false | Multi-value industry-fit filter (set-overlap). |
scene_type | query | any | false | Single-value scene/intent filter. |
limit | query | integer | false | |
offset | query | integer | false | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/site-templates' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/site-templates",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/site-templates", {
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/content/site-templates", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
400 | Bad request — malformed parameter |
404 | Resource not found |
422 | Validation failed for one of the query parameters |
429 | Rate limit exceeded |
500 | Internal server error |
Get a site template by slug
Fetch a single public site template by slug. No auth. 404 includes did_you_mean close-match suggestions.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | true | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/site-templates/{slug}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/site-templates/{slug}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/site-templates/{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/content/site-templates/{slug}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
400 | Bad request — malformed parameter |
404 | Resource not found |
422 | Validation failed for one of the query parameters |
429 | Rate limit exceeded |
500 | Internal server error |
Browse marketplace site templates (alias)
Alias of GET /content/site-templates. Same query surface.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
industry | query | any | false | |
use_case | query | any | false | |
tag | query | any | false | |
is_featured | query | any | false | |
is_single_page | query | any | false | true = single-page templates; false = whole-site; omit = both. |
mood | query | array[string] | false | |
palette | query | array[string] | false | |
brand_fit | query | array[string] | false | |
scene_type | query | any | false | |
limit | query | integer | false | |
offset | query | integer | false | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/marketplace/site-templates' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/marketplace/site-templates",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/marketplace/site-templates", {
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/content/marketplace/site-templates", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
400 | Bad request — malformed parameter |
404 | Resource not found |
422 | Validation failed for one of the query parameters |
429 | Rate limit exceeded |
500 | Internal server error |
Discover marketplace categories from live DB
Returns every DISTINCT marketplace_category value present in the global published catalog, with row counts. Powers the frontend's auto-discovery layer so a new value added via PATCH is immediately visible in the UI without a registry source change.
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/marketplace/category-counts' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/marketplace/category-counts",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/marketplace/category-counts", {
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/content/marketplace/category-counts", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Cross-table marketplace search
UNION search across content_bg_videos + content_components + content_site_templates with universal-axis filters. Public read. Returns a flat list of MarketplaceSearchItem rows projected to a common shape so agents can group_by(.asset_type). Backed by the GIN bitmap-AND indexes installed in migration 177; passing any of the controlled-vocab axes (mood / brand_fit / scene_type) is recommended to keep latency under 100ms even on the full catalog.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
asset_types | query | array[string] | false | Filter to specific asset tables. Allowed values: bg_video, component, site_template. Empty = all 3. |
mood | query | array[string] | false | Multi-value mood filter (set-overlap). |
palette | query | array[string] | false | |
brand_fit | query | array[string] | false | |
scene_type | query | any | false | |
is_featured | query | any | false | |
limit | query | integer | false | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/marketplace/search' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/marketplace/search",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/marketplace/search", {
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/content/marketplace/search", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
400 | Bad request — malformed parameter |
404 | Resource not found |
422 | Validation failed for one of the query parameters |
429 | Rate limit exceeded |
500 | Internal server error |
Get a marketplace component by slug
Fetch a single is_global marketplace component by slug. Public read. 404 includes did_you_mean close-match suggestions.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | true | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/marketplace/components/{slug}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/marketplace/components/{slug}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/marketplace/components/{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/content/marketplace/components/{slug}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
400 | Bad request — malformed parameter |
404 | Resource not found |
422 | Validation failed for one of the query parameters |
429 | Rate limit exceeded |
500 | Internal server error |
List public data sources
Read-side projection of the content_data_sources registry. Used by the page editor's Source Picker (Phase E) and the agent help endpoint. Each row describes a dynamic-block source: posts, authors, categories, tags, idap.countries, idap.cities, idap.streets, idap.businesses, idap.lead. Hierarchical sources expose a parent_id.
🔴 A Source Picker MUST filter on is_servable (ISU-8). Being registered and is_public is not the same as being servable: idap.cities/idap.countries/idap.streets are declared here but nothing in the database backs them, and the items door refuses them with 422 DATA_SOURCE_NOT_SERVABLE. That flag comes from the SAME predicate the door applies, so the two cannot drift — which is how four global palette components previously shipped with default bindings that could never fetch.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
parent_id | query | any | false | If provided, return only sources whose parent_id matches (hierarchy walk). |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/data-sources' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/data-sources",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/data-sources", {
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/content/data-sources", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
400 | Bad request — malformed parameter |
404 | Resource not found |
422 | Validation failed for one of the query parameters |
429 | Rate limit exceeded |
500 | Internal server error |
Aggregate a data source into chart buckets
Marketplace V2 W5.3 — backs the dynamic chart block. Returns an array of [{label, value}, ...] produced by aggregating the registered data source per the query params. Tenant isolation: client_id resolved from the X-Content-Domain header (same as all other public content endpoints).
Defence-in-depth: max_items is capped at 500 here AND in the SQL layer (server-side LIMIT clause). Pydantic enforces the same ceiling on inbound block validation. group_by_field + value_field are validated against the source's declared field types via data_source_registry.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
source_id | path | string | true | |
group_by | query | string | true | Source-schema field id to group buckets by. |
agg | query | string | false | Aggregation function. |
value_field | query | any | false | Required when agg in (sum, avg); ignored otherwise. |
max_items | query | integer | false | Max buckets to return. Hard-capped at 500 in SQL too. |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/data-sources/{source_id}/aggregate' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/data-sources/{source_id}/aggregate",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/data-sources/{source_id}/aggregate", {
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/content/data-sources/{source_id}/aggregate", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
400 | Bad request — malformed parameter |
404 | Resource not found |
422 | Validation failed for one of the query parameters |
429 | Rate limit exceeded |
500 | Internal server error |
List items from a registered data source
Backs the dynamic list / item blocks and any kind='dynamic' component bound to a collection. Returns an array of records from the registered source, filtered/sorted/paginated per the query params. Tenant isolation: client_id resolved from the X-Content-Domain header (same as all other public content endpoints); published content only.
Filters are passed as arbitrary query params matching the source's schema_json.filters (e.g. ?tag=news&category=...). sort is a single field with an optional :asc|:desc suffix; limit (1-500) + offset paginate; fields=slug,title projects. v1 sources: posts, authors, categories, tags, changelog.
idap.businesses is servable (ISU-8). It returns the tenant's own business corpus with every declared field id from the frozen public contract — review_count, phone and category are the caller-facing ids for the reviews_count, phone_e164 and categories columns, and sorting uses the resolved column. Its sibling idap.* collections are declared but not servable (nothing in the database backs them) and answer 422 DATA_SOURCE_NOT_SERVABLE rather than an empty list, so 'no rows' and 'no table' stay distinguishable. idap.lead is a singleton and still answers 422.
Deep paging: offset is capped at 10,000 and refuses past it with 422 OFFSET_CAP_EXCEEDED — it never silently serves a different page. Send the response's next_cursor as after= to traverse further at constant cost.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
source_id | path | string | true | |
limit | query | integer | false | Max records to return. |
offset | query | integer | false | Pagination offset (capped — see after). |
after | query | any | false | Keyset cursor from a previous response's next_cursor. Pages at constant cost regardless of depth; takes precedence over offset. |
sort | query | any | false | Sort field, optional :asc|:desc (or -field) suffix. |
fields | query | any | false | Comma-separated field ids to include; omit for all fields. |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/data-sources/{source_id}/items' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/data-sources/{source_id}/items",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/data-sources/{source_id}/items", {
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/content/data-sources/{source_id}/items", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
400 | Bad request — malformed parameter |
404 | Resource not found |
422 | Validation failed for one of the query parameters |
429 | Rate limit exceeded |
500 | Internal server error |
Get one published record of a public custom collection
The anonymous per-record detail door for a public custom collection (feeds the pretty-URL detail page — /<route_base>/<record-slug>). Returns the single record whose slug matches record_slug, with relationships hydrated one level (targets are public-only). Tenant isolation: client_id resolved from the X-Content-Domain header. Gated on the collection's is_public flag AND status='published' — a private collection, an unknown collection, and an absent/unpublished record all return 404 (a private collection is indistinguishable from an unknown one — no existence leak). All idap.* sources ship in Phase 2 → 501 (the decision-#29 PII structural-absence guarantee holds); built-in sources (posts/authors/…) have their own per-record endpoints and 404 here.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
source_id | path | string | true | |
record_slug | path | string | true | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/data-sources/{source_id}/items/{record_slug}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/data-sources/{source_id}/items/{record_slug}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/data-sources/{source_id}/items/{record_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/content/data-sources/{source_id}/items/{record_slug}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
400 | Bad request — malformed parameter |
404 | Resource not found |
422 | Validation failed for one of the query parameters |
429 | Rate limit exceeded |
500 | Internal server error |
Get one data source by id
Fetch a single content_data_sources row by id. 404 with did_you_mean suggestions when the id doesn't exist.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
source_id | path | string | true | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/data-sources/{source_id}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/data-sources/{source_id}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/data-sources/{source_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/content/data-sources/{source_id}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
400 | Bad request — malformed parameter |
404 | Resource not found |
422 | Validation failed for one of the query parameters |
429 | Rate limit exceeded |
500 | Internal server error |
Browse marketplace components
Browse the SpiderIQ section library. Public read — no auth. Phase D adds 5 universal-axis filters (mood, palette, brand_fit, scene_type, agent_meta.<key>) so agents can narrow by tonal / industry / behavioural axes. The vocabulary for each axis is served by GET /content/help → marketplace.universal_axes.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
category | query | any | false | Filter by marketplace_category (hero, features, pricing, social-proof, content, forms, team, footer, header, cta, faq). |
is_featured | query | any | false | Surface featured-only sections. |
tag | query | any | false | Tag filter (single tag). |
owner_client_id | query | any | false | Filter to components owned by this client_id (UUID or short-id). When set, returns ONLY rows owned by that client (system-namespace components are excluded). Defaults to None = include both system + brand-owned components, current behavior. Used by marketplace authoring brands to audit just-their-own counts (Antigravity Status Report #3, 2026-05-11). |
mood | query | array[string] | false | Multi-value mood filter (set-overlap). See /content/help. |
palette | query | array[string] | false | Multi-value palette filter (set-overlap). |
brand_fit | query | array[string] | false | Multi-value industry-fit filter (set-overlap). |
scene_type | query | any | false | Single-value scene/intent filter. |
limit | query | integer | false | |
offset | query | integer | false | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/marketplace/components' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/marketplace/components",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/marketplace/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/content/marketplace/components", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
400 | Bad request — malformed parameter |
404 | Resource not found |
422 | Validation failed for one of the query parameters |
429 | Rate limit exceeded |
500 | Internal server error |
Browse marketplace background videos
List curated background videos. Public read — no auth. Phase D adds 5 universal-axis filters (mood, palette, brand_fit, scene_type, agent_meta.<key>). Vocabulary served by /content/help.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
category | query | any | false | nature | city | abstract | food | tech | people |
tag | query | any | false | |
is_featured | query | any | false | |
mood | query | array[string] | false | Multi-value mood filter (set-overlap). |
palette | query | array[string] | false | Multi-value palette filter (set-overlap). |
brand_fit | query | array[string] | false | Multi-value industry-fit filter (set-overlap). |
scene_type | query | any | false | Single-value scene/intent filter. |
limit | query | integer | false | |
offset | query | integer | false | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/marketplace/bg-videos' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/marketplace/bg-videos",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/marketplace/bg-videos", {
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/content/marketplace/bg-videos", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
400 | Bad request — malformed parameter |
404 | Resource not found |
422 | Validation failed for one of the query parameters |
429 | Rate limit exceeded |
500 | Internal server error |
Get a marketplace background video by slug
Fetch a single bg-video by slug. Public read — no auth. 404 includes did_you_mean with closest-match slugs so an agent that hallucinates a slug gets a deterministic recovery path.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | true | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/marketplace/bg-videos/{slug}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/marketplace/bg-videos/{slug}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/marketplace/bg-videos/{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/content/marketplace/bg-videos/{slug}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
400 | Bad request — malformed parameter |
404 | Resource not found |
422 | Validation failed for one of the query parameters |
429 | Rate limit exceeded |
500 | Internal server error |
Recent customer events (PII-filtered)
Returns recent customer events for the toast component sys-proof-recent-sales-toast. Tenants publish events as posts in a category (default slug recent-sales) with structured custom_fields = {first_name, city, kind}. The endpoint NEVER emits last_name, email, phone, post body, title, or excerpt — only first_name + city + kind + occurred_at. Rows where first_name OR city is empty are dropped server-side. Window: events younger than min_age_minutes are suppressed; events older than max_age_hours are dropped.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
category | query | string | false | Post-category slug to read events from. |
min_age_minutes | query | integer | false | Suppress events younger than this many minutes (default 5). |
max_age_hours | query | integer | false | Drop events older than this many hours (default 72). |
limit | query | integer | false |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/proof/recent-sales' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/proof/recent-sales",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/proof/recent-sales", {
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/content/proof/recent-sales", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
400 | Bad request — malformed parameter |
404 | Resource not found |
422 | Validation failed for one of the query parameters |
429 | Rate limit exceeded |
500 | Internal server error |
Recent real transactional events (PII-redacted)
Honest Social Proof: returns recent REAL customer events for the social-proof toast / ticker components — union of completed Medusa orders, closed-won CRM deals, and confirmed SpiderBook bookings for the tenant. Redacted SERVER-SIDE to first_name + optional city + an optional product/service label + occurred_at; NEVER emits last name, email, phone, address, or amount. Rows without a first_name are dropped. Empty events means the tenant has no qualifying activity — the component MUST hide itself rather than fabricate. sources selects which real feeds to union (default: all three).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
sources | query | string | false | Comma-separated subset of orders,deals,bookings. |
min_age_minutes | query | integer | false | Suppress events younger than this many minutes (default 0). |
max_age_hours | query | integer | false | Drop events older than this many hours (default 72). |
limit | query | integer | false |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/proof/recent-activity' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/proof/recent-activity",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/proof/recent-activity", {
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/content/proof/recent-activity", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
400 | Bad request — malformed parameter |
404 | Resource not found |
422 | Validation failed for one of the query parameters |
429 | Rate limit exceeded |
500 | Internal server error |
Real bestselling product (order count)
Honest Social Proof: returns the tenant's REAL top-selling product by completed-order count over the window, for the bestseller-badge component. No PII. product_title is null when the tenant has no orders — the component MUST hide itself rather than claim a bestseller.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
max_age_hours | query | integer | false | How far back to count orders (default 30d). |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/proof/bestseller' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/proof/bestseller",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/proof/bestseller", {
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/content/proof/bestseller", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
400 | Bad request — malformed parameter |
404 | Resource not found |
422 | Validation failed for one of the query parameters |
429 | Rate limit exceeded |
500 | Internal server error |
Reflect Cloudflare visitor-geo headers
Returns the visitor's country / city / region / timezone as provided by Cloudflare's edge headers (CF-IPCountry, CF-IPCity, CF-Region, CF-Timezone). NO database lookup, NO IP storage — this is a stateless reflection of the edge enrichment plan. Country may be null when the request did not transit Cloudflare (local dev) or when CF returned XX / T1 (Tor / unknown). City and region are nullable on free CF zones.
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/visitor-geo' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/visitor-geo",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/visitor-geo", {
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/content/visitor-geo", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
429 | Rate limit exceeded |
500 | Internal server error |
Get Agent Rotation
The project's enabled paired agents (the renderer's round-robin rotation set).
Public, host-scoped — resolves client + project from X-Content-Domain exactly like the page reads, so the rotation set matches the rendered page's scope. The renderer reads this ONLY when a content row (or the project default) resolves to round_robin, then picks one statelessly by hashing the visitor key (no per-request write). Each entry's binding is fetched via /api/v1/booking/{id}/render.
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/agents/rotation' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/agents/rotation",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/agents/rotation", {
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/content/agents/rotation", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
List Pages
List all published marketing pages. Use ?format=json|yaml|md|llm for agent-friendly responses.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
page | query | integer | false | |
page_size | query | integer | false | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/pages' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/pages",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/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/content/pages", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Page
Get a published page by slug. Use ?format=json|yaml|md|llm for agent-friendly responses.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | true | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/pages/{slug}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/pages/{slug}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/pages/{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/content/pages/{slug}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
List Posts
List all published blog posts. Use ?format=json|yaml|md|llm for agent-friendly responses.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
page | query | integer | false | |
page_size | query | integer | false | |
tag | query | any | false | |
category | query | any | false | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/posts' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/posts",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/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/content/posts", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
List Featured Posts
List featured published posts. Use ?format=json|yaml|md|llm for agent-friendly responses.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
limit | query | integer | false | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/posts/featured' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/posts/featured",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/posts/featured", {
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/content/posts/featured", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Search Posts
Full-text search across published posts. Use ?format=json|yaml|md|llm for agent-friendly responses.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
q | query | string | true | |
page | query | integer | false | |
page_size | query | integer | false | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/posts/search' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/posts/search",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/posts/search", {
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/content/posts/search", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Post
Get a published blog post by slug. Increments view count. Use ?format=json|yaml|md|llm for agent-friendly responses.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | true | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/posts/{slug}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/posts/{slug}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/posts/{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/content/posts/{slug}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
List Categories
List all blog categories. Use ?format=json|yaml|md|llm for agent-friendly responses.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/categories' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/categories",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/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/content/categories", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
List Tags
List all tags with post counts. Use ?format=json|yaml|md|llm for agent-friendly responses.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/tags' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/tags",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/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/content/tags", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
List Authors
List all active authors. Use ?format=json|yaml|md|llm for agent-friendly responses.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
page | query | integer | false | |
page_size | query | integer | false | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/authors' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/authors",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/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/content/authors", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Author
Get an author by slug (public profile). Use ?format=json|yaml|md|llm for agent-friendly responses.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | true | |
format | query | any | false | Response format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/authors/{slug}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/authors/{slug}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/authors/{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/content/authors/{slug}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
List Components
List published components available for the site. Includes global (system) components and client-specific published components.
When slugs is provided, returns only the latest published version of each requested slug — ignoring page/page_size caps since the caller is asking for a known bounded set.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
category | query | any | false | Filter by component category |
slugs | query | any | false | Comma-separated list of component slugs to fetch (batch). Used by the Liquid renderer's per-page prefetch so it can grab all referenced components in one round-trip regardless of pagination / total count. |
page | query | integer | false | |
page_size | query | integer | false |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/components' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/components",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/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/content/components", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Component
Get a published component by slug. Used by the Liquid renderer Worker at render time to fetch component template + CSS + props schema.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | true | |
version | query | any | false | Specific version (default: latest published) |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/components/{slug}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/components/{slug}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/components/{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/content/components/{slug}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
List Cdn Allowlist
List active CDN libraries available for component dependencies. AI agents and the renderer use this to discover available libraries. No authentication required.
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/cdn-allowlist' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/cdn-allowlist",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/cdn-allowlist", {
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/content/cdn-allowlist", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Get Docs Tree
Get the full documentation tree structure. Client resolved from request domain.
Docs Platform v2 · 3.4 — ?version= scopes the tree to one docs version (omit → the tenant's default version). The response carries the tenant's published versions + the resolved current_version so the chrome can build the switcher from this single call.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
version | query | any | false |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/docs/tree' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/docs/tree",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/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/content/docs/tree", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Doc Versions
List a tenant's published docs versions for the chrome switcher (3.4).
Fixed-path route — MUST stay ABOVE /docs/{path:path} (the catch-all would otherwise match path='versions'). Same constraint as /docs/search.
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/docs/versions' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/docs/versions",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/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/content/docs/versions", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Capture Doc Event
Docs analytics beacon (3.4) — fire-and-forget, returns 202 immediately.
The capture insert runs in a background task so it never blocks the response (the doc.liquid beacon does not await meaningful work). Capture failures are swallowed inside the service. doc.liquid only ever sends view; search / ask are captured server-side in their own handlers.
Fixed-path route — MUST stay ABOVE /docs/{path:path}.
Try it
Examples
cURL
curl -X POST 'https://spideriq.ai/api/v1/content/docs/event' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"event_type": "string",
"doc_path": "string",
"version": "default",
"query_text": "string"
}'Python
import httpx
resp = httpx.post(
"https://spideriq.ai/api/v1/content/docs/event",
headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
json={"event_type": "string", "doc_path": "string", "version": "default", "query_text": "string"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/docs/event", {
method: "POST",
headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
body: JSON.stringify({"event_type": "string", "doc_path": "string", "version": "default", "query_text": "string"})
});
const data = await resp.json();
console.log(data);Go
package main
import (
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{"event_type": "string", "doc_path": "string", "version": "default", "query_text": "string"}`)
req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/content/docs/event", body)
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
202 | Successful Response |
422 | Validation Error |
Search Docs
Full-text search across the tenant's published docs.
Free (not metered) keyword search over title + body_text, scoped to the resolved tenant and status='published', excluding section rows. Returns ranked hits with ts_headline snippets: {title, full_path, section_title, snippet}. Consumed by the docs chrome search box (task 1.4).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
q | query | string | true | |
page | query | integer | false | |
page_size | query | integer | false |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/docs/search' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/docs/search",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/docs/search", {
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/content/docs/search", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Semantic Docs
Semantic (vector) search across the tenant's published docs (3.2).
Embeds the query through SpiderGate and returns the top-k most similar chunks with their source doc paths — meaning-based retrieval, the half of ask-the-docs exposed on its own for agents/clients that want raw passages rather than a synthesized answer. Per-IP rate-limited (embeddings are paid).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
q | query | string | true | |
top_k | query | integer | false |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/docs/semantic' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/docs/semantic",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/docs/semantic", {
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/content/docs/semantic", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Ask Docs
Ask-the-docs (3.2): a grounded AI answer over the tenant's published docs.
Retrieves the top-k relevant passages (semantic search), then asks a SpiderGate completion to answer using ONLY those passages, returning the answer plus the cited source links (sources[n] aligns with the [n] citations in the answer). METERED — all LLM calls route through SpiderGate (service_type='docs_ai'). The Docs-Pro entitlement + docs_ai quota are wired in task 3.5 via check_docs_ai_quota (a no-op seam here). Per-IP rate-limited.
Try it
Examples
cURL
curl -X POST 'https://spideriq.ai/api/v1/content/docs/ask' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"query": "string",
"top_k": 6
}'Python
import httpx
resp = httpx.post(
"https://spideriq.ai/api/v1/content/docs/ask",
headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
json={"query": "string", "top_k": 6},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/docs/ask", {
method: "POST",
headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
body: JSON.stringify({"query": "string", "top_k": 6})
});
const data = await resp.json();
console.log(data);Go
package main
import (
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{"query": "string", "top_k": 6}`)
req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/content/docs/ask", body)
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Docs Mcp
Hosted, per-tenant remote MCP server over this site's published docs (Docs Platform v2 · 3.3 — the headline moat).
Streamable-HTTP transport: a single JSON-RPC 2.0 endpoint. Any external AI agent (Claude / ChatGPT / Cursor) points its MCP client at https://<docs-domain>/api/v1/content/docs/mcp and gets four read-only, tenant-scoped, published-only tools: search_docs, semantic_search_docs, ask_docs (metered via the 3.5-M trusted internal path), get_doc. Tenant resolved from X-Content-Domain like every other /content/docs/* route. The server never initiates messages, so each POST gets a plain JSON response (no SSE needed); a request that is all notifications gets 202 Accepted with no body.
Try it
Examples
cURL
curl -X POST 'https://spideriq.ai/api/v1/content/docs/mcp' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.post(
"https://spideriq.ai/api/v1/content/docs/mcp",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/docs/mcp", {
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/content/docs/mcp", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Get Doc
Get a documentation page by full path. Path can be nested (e.g., "api/authentication/oauth").
Docs Platform v2 · 3.4 — ?version= selects a docs version (omit → the tenant's default). A page missing in a non-default version falls back to the default version's page rather than 404ing (graceful "only in latest").
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
path | path | string | true | |
version | query | any | false |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/docs/{path}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/docs/{path}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/docs/{path}", {
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/content/docs/{path}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Navigation
Get navigation menu by location. Locations: header, footer, docs_sidebar
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
location | path | string | true |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/navigation/{location}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/navigation/{location}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/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/content/navigation/{location}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Settings
Get site-wide content settings. Includes branding, social links, analytics IDs.
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/settings' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/settings",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/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/content/settings", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Get Members Jwks
Public, read-only proxy for the members sidecar's JWKS (§7.6 bridge).
The members sidecar (apps/auth-members) is loopback-bound + firewalled (§15 R1), so the CF edge — which cannot reach 127.0.0.1 — cannot fetch its JWKS directly. The api-gateway CAN reach auth-members:3002 over the docker network, so it proxies the sidecar's /api/auth/jwks here. The renderer fetches THIS and caches it in Worker KV (TTL + kid-rotation). No tenant context — the keyset is global to the members system.
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/members/jwks' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/members/jwks",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/members/jwks", {
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/content/members/jwks", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Get Members Gate Context
Per-request context the edge gate needs (project id + the two flags).
Resolves the request domain → its project's public id (proj_…) for the §15 R4 resolve_project(host) == jwt.project_id assertion, plus the per-tenant edge_auth_enabled flag and the global edge_auth_global kill-switch. The renderer fetches this only when a page's access is non-public (the public path never calls it → R6 no-op).
Fail-open posture: if the domain has no resolvable project the response is inert (project_id=null, edge_auth_enabled=false) and the edge renders the page ungated. This is safe because the renderer must ALREADY have resolved the same domain to fetch the page at all — a gate-context miss therefore only co-occurs with a page-fetch miss (the page wouldn't render either way). The global flag is always returned so an incident flip bypasses everything.
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/members/gate-context' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/members/gate-context",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/members/gate-context", {
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/content/members/gate-context", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Get Member Data Items
Member-scoped, Data-Restriction-filtered records for a gated page.
401 — no/invalid/expired member JWT. 403 — valid token for a DIFFERENT project (§15 R4). 404 — host not resolvable to a project, or a source with no v1 enforcement adapter. 200 — the member's permitted rows only.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
source_id | path | string | true | |
page | query | integer | false | |
page_size | query | integer | false |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/members/data-sources/{source_id}/items' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/members/data-sources/{source_id}/items",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/members/data-sources/{source_id}/items", {
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/content/members/data-sources/{source_id}/items", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Proxy Members Auth
Public, allowlisted reverse-proxy for the members sidecar's WRITE auth endpoints (§C2.5 same-host sign-in bridge). Forwards method/body/cookies to auth-members:3002/api/auth/* and passes Set-Cookie through unchanged.
A path not on the public allowlist → 404 (admin/org/token are never exposed).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
auth_path | path | string | true |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/members/auth/{auth_path}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/members/auth/{auth_path}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/members/auth/{auth_path}", {
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/content/members/auth/{auth_path}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Proxy Members Auth
Public, allowlisted reverse-proxy for the members sidecar's WRITE auth endpoints (§C2.5 same-host sign-in bridge). Forwards method/body/cookies to auth-members:3002/api/auth/* and passes Set-Cookie through unchanged.
A path not on the public allowlist → 404 (admin/org/token are never exposed).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
auth_path | path | string | true |
Try it
Examples
cURL
curl -X POST 'https://spideriq.ai/api/v1/content/members/auth/{auth_path}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.post(
"https://spideriq.ai/api/v1/content/members/auth/{auth_path}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/members/auth/{auth_path}", {
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/content/members/auth/{auth_path}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Proxy Members Auth
Public, allowlisted reverse-proxy for the members sidecar's WRITE auth endpoints (§C2.5 same-host sign-in bridge). Forwards method/body/cookies to auth-members:3002/api/auth/* and passes Set-Cookie through unchanged.
A path not on the public allowlist → 404 (admin/org/token are never exposed).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
auth_path | path | string | true |
Try it
Examples
cURL
curl -X OPTIONS 'https://spideriq.ai/api/v1/content/members/auth/{auth_path}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.options(
"https://spideriq.ai/api/v1/content/members/auth/{auth_path}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/members/auth/{auth_path}", {
method: "OPTIONS",
headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);Go
package main
import (
"net/http"
)
func main() {
req, _ := http.NewRequest("OPTIONS", "https://spideriq.ai/api/v1/content/members/auth/{auth_path}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Check Redirect
Check if a path has an active redirect. Used by Next.js middleware for redirect handling.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
path | query | string | true |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/redirects/check' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/redirects/check",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/redirects/check", {
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/content/redirects/check", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Playbook
Look up the canonical tool-sequence for a stated goal (Tier 4.5).
Index (no intent) is ~2 KB YAML — safe to call on every session start. Full recipe for one task is typically 500-1500 bytes.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
intent | query | any | false | Exact task key OR natural-language goal |
format | query | any | false | Response format. yaml (default) and md return text; json and llm return JSON. Any other value is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/playbook' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/playbook",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/playbook", {
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/content/playbook", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
List Directory Categories
List every directory category for this tenant.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
page | query | integer | false | |
page_size | query | integer | false |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/directory/categories' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/directory/categories",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/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/content/directory/categories", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
List Directory Listings
Every published listing for this tenant, flat and paginated.
Only status='published' is reachable — the status is not a parameter, so a draft listing is indistinguishable from one that does not exist.
total is returned on page 1 only. The count is a second full-predicate scan of the table on every call and no index makes it cheap; on later pages the field is null, which means "not measured", not "zero".
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
category | query | any | false | Narrow to one category slug. |
city | query | any | false | Narrow to one city (exact name). |
page | query | integer | false | |
page_size | query | integer | false |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/directory/listings' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/directory/listings",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/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/content/directory/listings", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Directory Listing Flat
A single published listing by slug alone, with no category in the URL.
The unique index is (category_id, slug), so two categories in one workspace can hold the same listing slug. Locked decision (owner, 2026-08-25): resolve by deterministic first match (ORDER BY category.sort_order, category.slug) and return category_slug in the body so the caller can see which one it got — never a 400. ?category= narrows.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
listing_slug | path | string | true | |
category | query | any | false | Optional — narrows to one category when a slug is ambiguous. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/directory/listings/{listing_slug}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/directory/listings/{listing_slug}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/directory/listings/{listing_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/content/directory/listings/{listing_slug}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Directory Category
Single category + the list of cities with listings inside it.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
category_slug | path | string | true |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/directory/categories/{category_slug}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/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/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/content/directory/categories/{category_slug}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Directory City
All listings in (category, city). 404 if the combo has zero published listings.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
category_slug | path | string | true | |
city_slug | path | string | true | |
page | query | integer | false | |
page_size | query | integer | false |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/directory/categories/{category_slug}/cities/{city_slug}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/directory/categories/{category_slug}/cities/{city_slug}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/directory/categories/{category_slug}/cities/{city_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/content/directory/categories/{category_slug}/cities/{city_slug}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Directory Listing
Single listing detail. city_slug is validated against the listing's actual city_slug.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
category_slug | path | string | true | |
city_slug | path | string | true | |
listing_slug | path | string | true |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/directory/categories/{category_slug}/cities/{city_slug}/{listing_slug}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/directory/categories/{category_slug}/cities/{city_slug}/{listing_slug}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/directory/categories/{category_slug}/cities/{city_slug}/{listing_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/content/directory/categories/{category_slug}/cities/{city_slug}/{listing_slug}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Sitemap
Generate XML sitemap for all published content. Includes pages, blog posts, and documentation.
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/sitemap.xml' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/sitemap.xml",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/sitemap.xml", {
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/content/sitemap.xml", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Get Sitemap Json
Get sitemap data as JSON (for programmatic access).
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/sitemap' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/sitemap",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/sitemap", {
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/content/sitemap", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Get Rss Feed
RSS 2.0 feed of published posts (sys-rss-feed extension).
Empty post list serves a valid empty channel — anti-hallucination per catalog/LEARNINGS.md: never return 500 from a content extension surface, even when the tenant has no published posts.
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/feed.xml' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/feed.xml",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/feed.xml", {
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/content/feed.xml", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Get Atom Feed
Atom 1.0 feed of published posts (sys-atom-feed extension).
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/atom.xml' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/atom.xml",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/atom.xml", {
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/content/atom.xml", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Get Json Feed
JSON Feed 1.1 of published posts (sys-feed-json extension).
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/feed.json' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/feed.json",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/feed.json", {
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/content/feed.json", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
List Public Changelog
Published changelog entries, newest first (drafts never exposed).
Paginated: page/page_size (the house pattern, echoed on the response) or the legacy limit/offset. total is the count of ALL matching entries, so a caller can page to the end.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
page | query | any | false | 1-based page number (house pattern; wins over limit/offset). |
page_size | query | any | false | Entries per page (1-200, default 50). |
limit | query | any | false | Legacy alias for page_size (audit §9 pagination). |
offset | query | any | false | Legacy alias — raw row offset. |
sort | query | string | false | Ordering, newest first. published_at (default) = release date. version = semver compared NUMERICALLY per component, so v2.10.0 sorts above v2.9.0 (a TEXT sort puts it between v2.1.0 and v2.2.0). |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/changelog' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/changelog",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/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/content/changelog", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Changelog Rss
RSS 2.0 feed of published changelog entries (per-IP rate-limited).
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/changelog/feed.xml' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/changelog/feed.xml",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/changelog/feed.xml", {
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/content/changelog/feed.xml", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Get Changelog Atom
Atom 1.0 feed of published changelog entries (per-IP rate-limited).
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/changelog/atom.xml' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/changelog/atom.xml",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/changelog/atom.xml", {
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/content/changelog/atom.xml", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Get Public Changelog Entry
One published changelog entry, by version string or id.
The detail door behind the renderer's /changelog/{version} route. Drafts are never resolvable — an unpublished entry 404s exactly like a missing one, so an unreleased version can't be read by guessing its URL.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
ref | path | string | true | Version string (v2.9.0 — the human URL) or the entry's UUID. Version is matched first. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/changelog/{ref}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/changelog/{ref}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/changelog/{ref}", {
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/content/changelog/{ref}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
List published press releases
Public newsroom index — published releases only, newest first. KEYSET paginated: pass the returned next_cursor back as cursor. An empty newsroom returns items: [] with HTTP 200, never a 404.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
release_type | query | any | false | press_release | statement | media_alert | newsbyte |
year | query | any | false | Publication year, e.g. 2026. |
cursor | query | any | false | Opaque keyset cursor — NOT a page number. |
limit | query | integer | false |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/press' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/press",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/press", {
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/content/press", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Press Rss Feed
RSS 2.0 feed of published press releases (press-feed extension).
Empty newsroom → a valid empty channel, HTTP 200 (never a 500) — same anti-hallucination contract as the posts feed.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
release_type | query | any | false | Optional filter: press_release | statement | media_alert | newsbyte. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/press/feed.xml' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/press/feed.xml",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/press/feed.xml", {
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/content/press/feed.xml", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Press Atom Feed
Atom 1.0 feed of published press releases.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
release_type | query | any | false |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/press/atom.xml' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/press/atom.xml",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/press/atom.xml", {
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/content/press/atom.xml", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Press Json Feed
JSON Feed 1.1 of published press releases.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
release_type | query | any | false |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/press/feed.json' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/press/feed.json",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/press/feed.json", {
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/content/press/feed.json", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
List public press contacts
The newsroom contact block, in display order. Unpaginated by design — a newsroom has tens of contacts, not thousands. Empty → items: [], 200.
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/press/contacts' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/press/contacts",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/press/contacts", {
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/content/press/contacts", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Get a public media kit
A story-scoped media kit with its downloadable assets. Unknown slug → 404.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | true |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/press/kits/{slug}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/press/kits/{slug}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/press/kits/{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/content/press/kits/{slug}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Download a media kit's full bundle
302 to the kit's pre-built ZIP and counts the download. No auth — press assets are deliberately ungated. 404 when the kit is unknown on this site or its bundle has not been built yet.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | true |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/press/kits/{slug}/download' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/press/kits/{slug}/download",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/press/kits/{slug}/download", {
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/content/press/kits/{slug}/download", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
302 | Successful Response |
422 | Validation Error |
Download one media-kit asset
302 to a single asset inside a kit and counts the download. No auth. 404 when the kit or the asset is unknown on this site.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | true | |
media_id | path | string | true |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/press/kits/{slug}/assets/{media_id}/download' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/press/kits/{slug}/assets/{media_id}/download",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/press/kits/{slug}/assets/{media_id}/download", {
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/content/press/kits/{slug}/assets/{media_id}/download", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
302 | Successful Response |
422 | Validation Error |
Subscribe to a newsroom's press releases
Public, unauthenticated. Starts a DOUBLE OPT-IN: the address is stored as pending and a confirmation link is emailed. Nothing is sent to the address until that link is clicked.
The response is identical for a new address, a repeat signup and an address already on the list — it never reveals list membership. 202 Accepted, because the confirmation mail is dispatched off the request path.
Try it
Examples
cURL
curl -X POST 'https://spideriq.ai/api/v1/content/press/subscribe' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"email": "string",
"topics": [
"string"
],
"source": "string"
}'Python
import httpx
resp = httpx.post(
"https://spideriq.ai/api/v1/content/press/subscribe",
headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
json={"email": "string", "topics": ["string"], "source": "string"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/press/subscribe", {
method: "POST",
headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
body: JSON.stringify({"email": "string", "topics": ["string"], "source": "string"})
});
const data = await resp.json();
console.log(data);Go
package main
import (
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{"email": "string", "topics": ["string"], "source": "string"}`)
req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/content/press/subscribe", body)
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
202 | Signup accepted; a confirmation email may have been sent. |
422 | The address is not a valid email address. |
429 | Too many signups from this IP. |
Confirmation landing page for a newsroom subscription
Renders the confirm page. READ-ONLY — clicking through does not subscribe anyone; the POST to the same path does. Invalid, expired and already-used tokens all render one generic page.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
token | query | string | true |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/press/subscribe/confirm' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/press/subscribe/confirm",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/press/subscribe/confirm", {
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/content/press/subscribe/confirm", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Confirm a newsroom subscription
Consumes the confirm token — SINGLE USE. Unknown, expired and already-spent tokens all return state: invalid with HTTP 200, so the endpoint cannot be used to probe tokens.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
token | query | string | true |
Try it
Examples
cURL
curl -X POST 'https://spideriq.ai/api/v1/content/press/subscribe/confirm' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.post(
"https://spideriq.ai/api/v1/content/press/subscribe/confirm",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/press/subscribe/confirm", {
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/content/press/subscribe/confirm", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Unsubscribe landing page
Renders the unsubscribe page. READ-ONLY — the POST to the same URL is what unsubscribes, and it is also the RFC 8058 one-click target.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
token | query | string | true |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/press/unsubscribe' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/press/unsubscribe",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/press/unsubscribe", {
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/content/press/unsubscribe", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Unsubscribe from a newsroom (RFC 8058 one-click target)
Applies the unsubscribe. Idempotent, never expires, and the token is deliberately NOT consumed — an unsubscribe link in an old inbox must keep working. This is the URL advertised in the List-Unsubscribe header of every release we send.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
token | query | string | true |
Try it
Examples
cURL
curl -X POST 'https://spideriq.ai/api/v1/content/press/unsubscribe' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.post(
"https://spideriq.ai/api/v1/content/press/unsubscribe",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/press/unsubscribe", {
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/content/press/unsubscribe", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Preview an embargoed press release with a journalist token
Renders an EMBARGOED release before its lift for a journalist holding a valid per-recipient token. Always robots: noindex,nofollow — a preview URL must never be indexed. The response NEVER carries embargo_token. An unknown/expired/cross-tenant token, or a token whose release does not match {slug}, returns 404 — identical to any missing release.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | true | |
token | query | string | true | Per-journalist embargo token |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/press/{slug}/embargo' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/press/{slug}/embargo",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/press/{slug}/embargo", {
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/content/press/{slug}/embargo", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get a published press release
One published release by slug. Draft, scheduled and EMBARGOED releases 404 here by design — the embargo token door is slice 3.2. The response NEVER carries embargo_token.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
slug | path | string | true | |
format | query | any | false | Response format. json (default) and llm return JSON; md returns text/markdown. This route has no YAML renderer, so yaml is a 422. |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/press/{slug}' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/press/{slug}",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/press/{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/content/press/{slug}", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Get Robots Txt
Generate /robots.txt for the requesting tenant.
Reads content_settings.extensions.robots:
enabled=false→ falls back to legacy minimal output.rules=[]→ emits oneUser-agent: * Allow: /group.auto_sitemap_link=true→ appendsSitemap: <origin>/sitemap.xml.extra_lines=[…]→ emitted verbatim before the sitemap line.
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/robots.txt' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/robots.txt",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/robots.txt", {
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/content/robots.txt", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Get Opensearch Xml
OpenSearch 1.1 description document (sys-opensearch-xml extension).
Reads content_settings.extensions.opensearch for short_name / description / search URL template / image overrides. Falls back to site_name / site_tagline / favicon_url when fields are unset so a fresh tenant still gets a browser-registerable description.
enabled=false in config → 410 Gone (browsers stop offering the search-engine registration without retrying).
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/opensearch.xml' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/opensearch.xml",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/opensearch.xml", {
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/content/opensearch.xml", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Get Llms Txt
llms.txt for LLM crawlers (sys-llms-txt extension).
Structure preset selected via content_settings.extensions.llms_txt.structure: one of minimal | blog-only | fastapi-style (default) | mintlify. include_authors appends post authors to bullets. max_items_per_section is clamped to [1, 500].
Each preset only fetches the data it needs:
- minimal → docs tree only
- blog-only → posts only
- fastapi-style → pages + posts + docs
- mintlify → docs + posts (sectionable docs preferred)
enabled=false in config → 410 Gone.
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/llms.txt' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/llms.txt",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/llms.txt", {
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/content/llms.txt", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Get Llms Full Txt
llms-full.txt — the full Markdown body of a tenant's content (SEO 2.3).
Where /llms.txt is an INDEX (titles + links), this is the CONTENT: every published, indexable page/post/doc serialized to Markdown and concatenated in sitemap order (pages → posts → docs), each as ## {title}\nSource: {url}\n\n{markdown}.
OPT-IN per tenant via content_settings.extensions.llms_txt.full_enabled (default FALSE). When the parent llms_txt surface is disabled, or full_enabled is off, this returns 404 — the full corpus is an explicit choice, not an always-on surface.
Size governance (NO silent truncation): the body is capped by full_max_items and full_max_bytes (both clamped server-side); when content is dropped, a trailing > (truncated: N of M pages …) marker is appended. Hard-cached (crawler-facing, low-traffic).
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/llms-full.txt' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/llms-full.txt",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/llms-full.txt", {
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/content/llms-full.txt", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
Resolve Lead
Resolve a lead/business by external identifier for dynamic landing pages.
Used by the Liquid renderer to fetch lead data at render time. Resolves the client from X-Content-Domain header (same as all content endpoints). Returns the full business record with optional includes.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
place_id | query | any | false | Google Place ID (e.g. 0x47e66fdad6f1cc73:0x341211b3fccd79e1) |
domain | query | any | false | Domain name |
email | query | any | false | Email address |
pin_name | query | any | false | VayaPin pin name — resolves the business linked to this pin |
pin_data_set_id | query | any | false | VayaPin pin data-set ID — resolves the linked business |
account_id | query | any | false | VayaPin account ID — resolves the linked business |
pin_subscription_id | query | any | false | VayaPin pin subscription ID — resolves the linked business |
vat | query | any | false | VAT number — resolves the business linked to this registry record |
lei | query | any | false | Legal Entity Identifier (LEI) — resolves the linked business |
tax_id | query | any | false | Tax identification number — resolves the linked business |
registration_number | query | any | false | Company registration number — resolves the linked business |
include | query | any | false | Comma-separated related types (emails,phones,domains,contacts) |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/leads/resolve' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/leads/resolve",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/leads/resolve", {
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/content/leads/resolve", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Submit a dynamic form-block fill
Public form submission endpoint for the Marketplace V2 dynamic form block. form_id is composed as <page_uuid>:<block_uuid> — the service resolves the owning tenant from the page row (never from the URL or body), so the same form_id from a different tenant cannot be replayed against this site. The request body is validated against the resolved block's props.fields list; unknown fields are rejected. When props.submit_url is set the submission is also POSTed there as JSON; when props.fallback_idap_lead is true (default), the submission is persisted to content_form_submissions.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
form_id | path | string | true |
Try it
Examples
cURL
curl -X POST 'https://spideriq.ai/api/v1/content/forms/{form_id}/submit' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"submission": {},
"request_id": "string"
}'Python
import httpx
resp = httpx.post(
"https://spideriq.ai/api/v1/content/forms/{form_id}/submit",
headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
json={"submission": {}, "request_id": "string"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/forms/{form_id}/submit", {
method: "POST",
headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
body: JSON.stringify({"submission": {}, "request_id": "string"})
});
const data = await resp.json();
console.log(data);Go
package main
import (
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{"submission": {}, "request_id": "string"}`)
req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/content/forms/{form_id}/submit", body)
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
400 | Bad request — malformed parameter |
404 | Resource not found |
422 | Validation failed for one of the query parameters |
429 | Rate limit exceeded |
500 | Internal server error |
Get Vayapin Cards
Resolve VayaPin "cards" for rendering on pages / blog posts.
Global directory — NOT tenant-scoped, so no domain resolution. The Liquid renderer (and agents) call this to bake card data into a page at build time. Only public + listed pins are returned.
- Pinned mode (
?pins=BB:TAPAS,BB:CHAMPERS): exact card per named pin, in the order given, with any unresolved names reported back. - Query mode (
?q=/?country=/?city=/?category=): a list of cards.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
pins | query | any | false | Comma-separated pin ids (e.g. 'BB:TAPAS,BB:CHAMPERS'). Pinned mode — resolves each named pin to its exact card. |
q | query | any | false | Full-text query (query mode) |
country | query | any | false | 2-letter pin namespace, e.g. 'bb' (query mode) |
city | query | any | false | City / settlement filter (query mode) |
category | query | any | false | Category slug, e.g. 'restaurant' (query mode) |
limit | query | integer | false | Max cards in query mode |
Try it
Examples
cURL
curl -X GET 'https://spideriq.ai/api/v1/content/vayapin/cards' \
-H 'Authorization: Bearer <token>'Python
import httpx
resp = httpx.get(
"https://spideriq.ai/api/v1/content/vayapin/cards",
headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/vayapin/cards", {
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/content/vayapin/cards", nil)
req.Header.Set("Authorization", "Bearer <token>")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |
Submit Doc Feedback
Record a 'was this helpful?' vote for the resolved tenant's doc.
Returns 201 with a tiny ack envelope. 429 if the per-IP/tenant window is exceeded; 400/422 on bad input (handled by FastAPI/Pydantic); generic 500 on an internal error (never leaks the cause).
Try it
Examples
cURL
curl -X POST 'https://spideriq.ai/api/v1/content/docs/feedback' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"doc_path": "string",
"helpful": true,
"comment": "string"
}'Python
import httpx
resp = httpx.post(
"https://spideriq.ai/api/v1/content/docs/feedback",
headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
json={"doc_path": "string", "helpful": true, "comment": "string"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/docs/feedback", {
method: "POST",
headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
body: JSON.stringify({"doc_path": "string", "helpful": true, "comment": "string"})
});
const data = await resp.json();
console.log(data);Go
package main
import (
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{"doc_path": "string", "helpful": true, "comment": "string"}`)
req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/content/docs/feedback", body)
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
201 | Successful Response |
422 | Validation Error |
Playground Request
Relay one user-composed request to the imported API and return its response.
The target host is fixed server-side to the imported spec's declared base URL (persisted on the doc), never the client's choice. Returns {status, headers, body, elapsed_ms}. 400 if the doc has no playground base URL or the relay is refused (SSRF / method / size / timeout — all with a safe, instructive message); 429 if rate-limited; generic 500 on an internal error.
Try it
Examples
cURL
curl -X POST 'https://spideriq.ai/api/v1/content/docs/playground/request' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"doc_path": "string",
"method": "string",
"path": "string",
"query": {},
"headers": {},
"body": "string"
}'Python
import httpx
resp = httpx.post(
"https://spideriq.ai/api/v1/content/docs/playground/request",
headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
json={"doc_path": "string", "method": "string", "path": "string", "query": {}, "headers": {}, "body": "string"},
)
resp.raise_for_status()
print(resp.json())JavaScript
const resp = await fetch("https://spideriq.ai/api/v1/content/docs/playground/request", {
method: "POST",
headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
body: JSON.stringify({"doc_path": "string", "method": "string", "path": "string", "query": {}, "headers": {}, "body": "string"})
});
const data = await resp.json();
console.log(data);Go
package main
import (
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{"doc_path": "string", "method": "string", "path": "string", "query": {}, "headers": {}, "body": "string"}`)
req, _ := http.NewRequest("POST", "https://spideriq.ai/api/v1/content/docs/playground/request", body)
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}Responses
| Status | Description |
|---|---|
200 | Successful Response |
422 | Validation Error |