SSpiderIQ
SSpiderIQ

Docs / api-reference/content

Content

94 endpoints from the published OpenAPI import.

GET/api/v1/content/help

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

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/help/block-fields

Content Block Fields

E.2 (2026-05-22 Claude Code usability F-16) — per-block-type field map.

Returns:

  • All block types when block_type is 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

NameInTypeRequiredDescription
block_typequeryanyfalseIf set, return only the entry for this block_type. Omit to list all.
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/variables

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

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/themes

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

StatusDescription
200Successful Response
GET/api/v1/content/themes/{name}

Get Theme Detail

Get a theme's details and all template files (public, no auth).

Parameters

NameInTypeRequiredDescription
namepathstringtrue
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/site-templates

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

NameInTypeRequiredDescription
industryqueryanyfalse
use_casequeryanyfalse
tagqueryanyfalseFilter to templates that have this tag
is_featuredqueryanyfalse
is_single_pagequeryanyfalsetrue = single-page templates (opt-in/thankyou/VSL); false = whole-site templates; omit = both.
moodqueryarray[string]falseMulti-value mood filter (set-overlap).
palettequeryarray[string]falseMulti-value palette filter (set-overlap).
brand_fitqueryarray[string]falseMulti-value industry-fit filter (set-overlap).
scene_typequeryanyfalseSingle-value scene/intent filter.
limitqueryintegerfalse
offsetqueryintegerfalse
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
400Bad request — malformed parameter
404Resource not found
422Validation failed for one of the query parameters
429Rate limit exceeded
500Internal server error
GET/api/v1/content/site-templates/{slug}

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

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
400Bad request — malformed parameter
404Resource not found
422Validation failed for one of the query parameters
429Rate limit exceeded
500Internal server error
GET/api/v1/content/marketplace/site-templates

Browse marketplace site templates (alias)

Alias of GET /content/site-templates. Same query surface.

Parameters

NameInTypeRequiredDescription
industryqueryanyfalse
use_casequeryanyfalse
tagqueryanyfalse
is_featuredqueryanyfalse
is_single_pagequeryanyfalsetrue = single-page templates; false = whole-site; omit = both.
moodqueryarray[string]false
palettequeryarray[string]false
brand_fitqueryarray[string]false
scene_typequeryanyfalse
limitqueryintegerfalse
offsetqueryintegerfalse
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
400Bad request — malformed parameter
404Resource not found
422Validation failed for one of the query parameters
429Rate limit exceeded
500Internal server error
GET/api/v1/content/marketplace/category-counts

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

StatusDescription
200Successful Response
GET/api/v1/content/marketplace/search

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

NameInTypeRequiredDescription
asset_typesqueryarray[string]falseFilter to specific asset tables. Allowed values: bg_video, component, site_template. Empty = all 3.
moodqueryarray[string]falseMulti-value mood filter (set-overlap).
palettequeryarray[string]false
brand_fitqueryarray[string]false
scene_typequeryanyfalse
is_featuredqueryanyfalse
limitqueryintegerfalse
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
400Bad request — malformed parameter
404Resource not found
422Validation failed for one of the query parameters
429Rate limit exceeded
500Internal server error
GET/api/v1/content/marketplace/components/{slug}

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

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
400Bad request — malformed parameter
404Resource not found
422Validation failed for one of the query parameters
429Rate limit exceeded
500Internal server error
GET/api/v1/content/data-sources

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

NameInTypeRequiredDescription
parent_idqueryanyfalseIf provided, return only sources whose parent_id matches (hierarchy walk).
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
400Bad request — malformed parameter
404Resource not found
422Validation failed for one of the query parameters
429Rate limit exceeded
500Internal server error
GET/api/v1/content/data-sources/{source_id}/aggregate

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

NameInTypeRequiredDescription
source_idpathstringtrue
group_byquerystringtrueSource-schema field id to group buckets by.
aggquerystringfalseAggregation function.
value_fieldqueryanyfalseRequired when agg in (sum, avg); ignored otherwise.
max_itemsqueryintegerfalseMax buckets to return. Hard-capped at 500 in SQL too.
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
400Bad request — malformed parameter
404Resource not found
422Validation failed for one of the query parameters
429Rate limit exceeded
500Internal server error
GET/api/v1/content/data-sources/{source_id}/items

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

NameInTypeRequiredDescription
source_idpathstringtrue
limitqueryintegerfalseMax records to return.
offsetqueryintegerfalsePagination offset (capped — see after).
afterqueryanyfalseKeyset cursor from a previous response's next_cursor. Pages at constant cost regardless of depth; takes precedence over offset.
sortqueryanyfalseSort field, optional :asc|:desc (or -field) suffix.
fieldsqueryanyfalseComma-separated field ids to include; omit for all fields.
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
400Bad request — malformed parameter
404Resource not found
422Validation failed for one of the query parameters
429Rate limit exceeded
500Internal server error
GET/api/v1/content/data-sources/{source_id}/items/{record_slug}

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

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
400Bad request — malformed parameter
404Resource not found
422Validation failed for one of the query parameters
429Rate limit exceeded
500Internal server error
GET/api/v1/content/data-sources/{source_id}

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

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
400Bad request — malformed parameter
404Resource not found
422Validation failed for one of the query parameters
429Rate limit exceeded
500Internal server error
GET/api/v1/content/marketplace/components

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

NameInTypeRequiredDescription
categoryqueryanyfalseFilter by marketplace_category (hero, features, pricing, social-proof, content, forms, team, footer, header, cta, faq).
is_featuredqueryanyfalseSurface featured-only sections.
tagqueryanyfalseTag filter (single tag).
owner_client_idqueryanyfalseFilter 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).
moodqueryarray[string]falseMulti-value mood filter (set-overlap). See /content/help.
palettequeryarray[string]falseMulti-value palette filter (set-overlap).
brand_fitqueryarray[string]falseMulti-value industry-fit filter (set-overlap).
scene_typequeryanyfalseSingle-value scene/intent filter.
limitqueryintegerfalse
offsetqueryintegerfalse
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
400Bad request — malformed parameter
404Resource not found
422Validation failed for one of the query parameters
429Rate limit exceeded
500Internal server error
GET/api/v1/content/marketplace/bg-videos

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

NameInTypeRequiredDescription
categoryqueryanyfalsenature | city | abstract | food | tech | people
tagqueryanyfalse
is_featuredqueryanyfalse
moodqueryarray[string]falseMulti-value mood filter (set-overlap).
palettequeryarray[string]falseMulti-value palette filter (set-overlap).
brand_fitqueryarray[string]falseMulti-value industry-fit filter (set-overlap).
scene_typequeryanyfalseSingle-value scene/intent filter.
limitqueryintegerfalse
offsetqueryintegerfalse
formatqueryanyfalseResponse format. json (default) and llm return JSON; yaml returns text/yaml; md returns text/markdown. Any other value is a 422.
Try it
Query

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
400Bad request — malformed parameter
404Resource not found
422Validation failed for one of the query parameters
429Rate limit exceeded
500Internal server error
GET/api/v1/content/marketplace/bg-videos/{slug}

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

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
400Bad request — malformed parameter
404Resource not found
422Validation failed for one of the query parameters
429Rate limit exceeded
500Internal server error
GET/api/v1/content/proof/recent-sales

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

NameInTypeRequiredDescription
categoryquerystringfalsePost-category slug to read events from.
min_age_minutesqueryintegerfalseSuppress events younger than this many minutes (default 5).
max_age_hoursqueryintegerfalseDrop events older than this many hours (default 72).
limitqueryintegerfalse
Try it
Query

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

StatusDescription
200Successful Response
400Bad request — malformed parameter
404Resource not found
422Validation failed for one of the query parameters
429Rate limit exceeded
500Internal server error
GET/api/v1/content/proof/recent-activity

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

NameInTypeRequiredDescription
sourcesquerystringfalseComma-separated subset of orders,deals,bookings.
min_age_minutesqueryintegerfalseSuppress events younger than this many minutes (default 0).
max_age_hoursqueryintegerfalseDrop events older than this many hours (default 72).
limitqueryintegerfalse
Try it
Query

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

StatusDescription
200Successful Response
400Bad request — malformed parameter
404Resource not found
422Validation failed for one of the query parameters
429Rate limit exceeded
500Internal server error
GET/api/v1/content/proof/bestseller

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

NameInTypeRequiredDescription
max_age_hoursqueryintegerfalseHow far back to count orders (default 30d).
Try it
Query

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

StatusDescription
200Successful Response
400Bad request — malformed parameter
404Resource not found
422Validation failed for one of the query parameters
429Rate limit exceeded
500Internal server error
GET/api/v1/content/visitor-geo

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

StatusDescription
200Successful Response
429Rate limit exceeded
500Internal server error
GET/api/v1/content/agents/rotation

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

StatusDescription
200Successful Response
GET/api/v1/content/pages

List Pages

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

Parameters

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/pages/{slug}

Get Page

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

Parameters

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/posts

List Posts

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

Parameters

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/posts/featured

List Featured Posts

List featured published posts. Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/posts/search

Search Posts

Full-text search across published posts. Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/posts/{slug}

Get Post

Get a published blog post by slug. Increments view count. Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/categories

List Categories

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

Parameters

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/tags

List Tags

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

Parameters

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/authors

List Authors

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

Parameters

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/authors/{slug}

Get Author

Get an author by slug (public profile). Use ?format=json|yaml|md|llm for agent-friendly responses.

Parameters

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/components

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

NameInTypeRequiredDescription
categoryqueryanyfalseFilter by component category
slugsqueryanyfalseComma-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.
pagequeryintegerfalse
page_sizequeryintegerfalse
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/components/{slug}

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

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

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/cdn-allowlist

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

StatusDescription
200Successful Response
GET/api/v1/content/docs/tree

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

NameInTypeRequiredDescription
versionqueryanyfalse
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/docs/versions

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

StatusDescription
200Successful Response
POST/api/v1/content/docs/event

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

StatusDescription
202Successful Response
422Validation Error
GET/api/v1/content/docs/search

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

NameInTypeRequiredDescription
qquerystringtrue
pagequeryintegerfalse
page_sizequeryintegerfalse
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/docs/semantic

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

NameInTypeRequiredDescription
qquerystringtrue
top_kqueryintegerfalse
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
POST/api/v1/content/docs/ask

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

StatusDescription
200Successful Response
422Validation Error
POST/api/v1/content/docs/mcp

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

StatusDescription
200Successful Response
GET/api/v1/content/docs/{path}

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

NameInTypeRequiredDescription
pathpathstringtrue
versionqueryanyfalse
Try it
Query

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

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

Get Navigation

Get navigation menu by location. Locations: header, footer, docs_sidebar

Parameters

NameInTypeRequiredDescription
locationpathstringtrue
Try it
Query

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

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

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

StatusDescription
200Successful Response
GET/api/v1/content/members/jwks

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

StatusDescription
200Successful Response
GET/api/v1/content/members/gate-context

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

StatusDescription
200Successful Response
GET/api/v1/content/members/data-sources/{source_id}/items

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

NameInTypeRequiredDescription
source_idpathstringtrue
pagequeryintegerfalse
page_sizequeryintegerfalse
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/members/auth/{auth_path}

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

NameInTypeRequiredDescription
auth_pathpathstringtrue
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
POST/api/v1/content/members/auth/{auth_path}

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

NameInTypeRequiredDescription
auth_pathpathstringtrue
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
OPTIONS/api/v1/content/members/auth/{auth_path}

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

NameInTypeRequiredDescription
auth_pathpathstringtrue
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/redirects/check

Check Redirect

Check if a path has an active redirect. Used by Next.js middleware for redirect handling.

Parameters

NameInTypeRequiredDescription
pathquerystringtrue
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/playbook

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

NameInTypeRequiredDescription
intentqueryanyfalseExact task key OR natural-language goal
formatqueryanyfalseResponse format. yaml (default) and md return text; json and llm return JSON. Any other value is a 422.
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/directory/categories

List Directory Categories

List every directory category for this tenant.

Parameters

NameInTypeRequiredDescription
pagequeryintegerfalse
page_sizequeryintegerfalse
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/directory/listings

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

NameInTypeRequiredDescription
categoryqueryanyfalseNarrow to one category slug.
cityqueryanyfalseNarrow to one city (exact name).
pagequeryintegerfalse
page_sizequeryintegerfalse
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/directory/listings/{listing_slug}

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

NameInTypeRequiredDescription
listing_slugpathstringtrue
categoryqueryanyfalseOptional — narrows to one category when a slug is ambiguous.
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/directory/categories/{category_slug}

Get Directory Category

Single category + the list of cities with listings inside it.

Parameters

NameInTypeRequiredDescription
category_slugpathstringtrue
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/directory/categories/{category_slug}/cities/{city_slug}

Get Directory City

All listings in (category, city). 404 if the combo has zero published listings.

Parameters

NameInTypeRequiredDescription
category_slugpathstringtrue
city_slugpathstringtrue
pagequeryintegerfalse
page_sizequeryintegerfalse
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/directory/categories/{category_slug}/cities/{city_slug}/{listing_slug}

Get Directory Listing

Single listing detail. city_slug is validated against the listing's actual city_slug.

Parameters

NameInTypeRequiredDescription
category_slugpathstringtrue
city_slugpathstringtrue
listing_slugpathstringtrue
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/sitemap.xml

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

StatusDescription
200Successful Response
GET/api/v1/content/sitemap

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

StatusDescription
200Successful Response
GET/api/v1/content/feed.xml

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

StatusDescription
200Successful Response
GET/api/v1/content/atom.xml

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

StatusDescription
200Successful Response
GET/api/v1/content/feed.json

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

StatusDescription
200Successful Response
GET/api/v1/content/changelog

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

NameInTypeRequiredDescription
pagequeryanyfalse1-based page number (house pattern; wins over limit/offset).
page_sizequeryanyfalseEntries per page (1-200, default 50).
limitqueryanyfalseLegacy alias for page_size (audit §9 pagination).
offsetqueryanyfalseLegacy alias — raw row offset.
sortquerystringfalseOrdering, 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
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/changelog/feed.xml

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

StatusDescription
200Successful Response
GET/api/v1/content/changelog/atom.xml

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

StatusDescription
200Successful Response
GET/api/v1/content/changelog/{ref}

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

NameInTypeRequiredDescription
refpathstringtrueVersion string (v2.9.0 — the human URL) or the entry's UUID. Version is matched first.
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/press

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

NameInTypeRequiredDescription
release_typequeryanyfalsepress_release | statement | media_alert | newsbyte
yearqueryanyfalsePublication year, e.g. 2026.
cursorqueryanyfalseOpaque keyset cursor — NOT a page number.
limitqueryintegerfalse
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/press/feed.xml

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

NameInTypeRequiredDescription
release_typequeryanyfalseOptional filter: press_release | statement | media_alert | newsbyte.
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/press/atom.xml

Get Press Atom Feed

Atom 1.0 feed of published press releases.

Parameters

NameInTypeRequiredDescription
release_typequeryanyfalse
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/press/feed.json

Get Press Json Feed

JSON Feed 1.1 of published press releases.

Parameters

NameInTypeRequiredDescription
release_typequeryanyfalse
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/press/contacts

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

StatusDescription
200Successful Response
GET/api/v1/content/press/kits/{slug}

Get a public media kit

A story-scoped media kit with its downloadable assets. Unknown slug → 404.

Parameters

NameInTypeRequiredDescription
slugpathstringtrue
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/press/kits/{slug}/download

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

NameInTypeRequiredDescription
slugpathstringtrue
Try it
Query

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

StatusDescription
302Successful Response
422Validation Error
GET/api/v1/content/press/kits/{slug}/assets/{media_id}/download

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

NameInTypeRequiredDescription
slugpathstringtrue
media_idpathstringtrue
Try it
Query

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

StatusDescription
302Successful Response
422Validation Error
POST/api/v1/content/press/subscribe

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

StatusDescription
202Signup accepted; a confirmation email may have been sent.
422The address is not a valid email address.
429Too many signups from this IP.
GET/api/v1/content/press/subscribe/confirm

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

NameInTypeRequiredDescription
tokenquerystringtrue
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
POST/api/v1/content/press/subscribe/confirm

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

NameInTypeRequiredDescription
tokenquerystringtrue
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/press/unsubscribe

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

NameInTypeRequiredDescription
tokenquerystringtrue
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
POST/api/v1/content/press/unsubscribe

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

NameInTypeRequiredDescription
tokenquerystringtrue
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/press/{slug}/embargo

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

NameInTypeRequiredDescription
slugpathstringtrue
tokenquerystringtruePer-journalist embargo token
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/press/{slug}

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

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

Examples

cURL
curl -X GET 'https://spideriq.ai/api/v1/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

StatusDescription
200Successful Response
422Validation Error
GET/api/v1/content/robots.txt

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 one User-agent: * Allow: / group.
  • auto_sitemap_link=true → appends Sitemap: <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

StatusDescription
200Successful Response
GET/api/v1/content/opensearch.xml

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

StatusDescription
200Successful Response
GET/api/v1/content/llms.txt

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

StatusDescription
200Successful Response
GET/api/v1/content/llms-full.txt

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

StatusDescription
200Successful Response
GET/api/v1/content/leads/resolve

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

NameInTypeRequiredDescription
place_idqueryanyfalseGoogle Place ID (e.g. 0x47e66fdad6f1cc73:0x341211b3fccd79e1)
domainqueryanyfalseDomain name
emailqueryanyfalseEmail address
pin_namequeryanyfalseVayaPin pin name — resolves the business linked to this pin
pin_data_set_idqueryanyfalseVayaPin pin data-set ID — resolves the linked business
account_idqueryanyfalseVayaPin account ID — resolves the linked business
pin_subscription_idqueryanyfalseVayaPin pin subscription ID — resolves the linked business
vatqueryanyfalseVAT number — resolves the business linked to this registry record
leiqueryanyfalseLegal Entity Identifier (LEI) — resolves the linked business
tax_idqueryanyfalseTax identification number — resolves the linked business
registration_numberqueryanyfalseCompany registration number — resolves the linked business
includequeryanyfalseComma-separated related types (emails,phones,domains,contacts)
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
POST/api/v1/content/forms/{form_id}/submit

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

NameInTypeRequiredDescription
form_idpathstringtrue
Try it
Query

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

StatusDescription
200Successful Response
400Bad request — malformed parameter
404Resource not found
422Validation failed for one of the query parameters
429Rate limit exceeded
500Internal server error
GET/api/v1/content/vayapin/cards

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

NameInTypeRequiredDescription
pinsqueryanyfalseComma-separated pin ids (e.g. 'BB:TAPAS,BB:CHAMPERS'). Pinned mode — resolves each named pin to its exact card.
qqueryanyfalseFull-text query (query mode)
countryqueryanyfalse2-letter pin namespace, e.g. 'bb' (query mode)
cityqueryanyfalseCity / settlement filter (query mode)
categoryqueryanyfalseCategory slug, e.g. 'restaurant' (query mode)
limitqueryintegerfalseMax cards in query mode
Try it
Query

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

StatusDescription
200Successful Response
422Validation Error
POST/api/v1/content/docs/feedback

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

StatusDescription
201Successful Response
422Validation Error
POST/api/v1/content/docs/playground/request

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

StatusDescription
200Successful Response
422Validation Error