Synerise Solutions API

Public, read-only HTTP API for retrieving the structured content behind

synerise.com/solutions/* pages. Built so partners, integrators, and

documentation tooling can consume the same source of truth that powers the

website itself, without scraping HTML.

The API is shipped page-by-page. Each /solutions/* page that opts in

exports a co-located solutionContent literal and is added to the API

whitelist. The pilot ships **brickworks**; subsequent rollout tasks add

slugs (ai-search, cdp, retail-media, synerise-agent,

ai-recommendations, data-transformation, …) as one-line whitelist

changes.

Base URL

https://www.synerise.com/api/v1/solutions

All endpoints are GET-only. CORS is open (`Access-Control-Allow-Origin:

*) for GET and OPTIONS`. Responses are JSON with

Cache-Control: public, max-age=300.

Rate limit

Each IP is limited to 60 requests per minute on the Solutions API on

top of the global Synerise public-API limit of 100 req/min.

Stability

v1 will continue to serve schemaVersion: 1 for at least 12 months

after a successor ships.

sections will be retained as empty placeholders for at least one major

version where feasible.

Endpoints

GET /api/v1/solutions

Returns the index of whitelisted solutions.

[
  {
    "slug": "brickworks",
    "title": "Brickworks — Schema-based. AI-native. One API.",
    "description": "Build custom data structures for loyalty programs, catalogs, and campaigns — with AI-native personalization, federated data, single-API delivery, and AI-agent-ready outputs.",
    "canonicalPath": "/solutions/brickworks"
  }
]

GET /api/v1/solutions/:slug

Returns the full SolutionContent payload for :slug.

Top-level shape:

{
  "schemaVersion": 1,
  "slug": "brickworks",
  "title": string,
  "description": string,
  "canonicalPath": "/solutions/brickworks",
  "locale": "en",
  "seo": { title, description, ogImage?, ogType?, canonicalPath },
  "sections": SolutionSection[]
}

locale is reserved for future localization; the pilot emits only

"en".

Unknown slugs return 404 with { "error": "not_found" }.

GET /api/v1/solutions/:slug/:sectionId

Returns a single section from a solution by its id. Section ids are

unique kebab-case strings within a solution. Unknown slug or section id

returns 404 { "error": "not_found" }.

Section kinds

Every section has { kind, id, ...fields }. The pilot supports these

kinds; each is a discriminated union member of SolutionSection.

KindNotable fields
heroeyebrow?, title, lead?, media?, ctas?
statstitle?, items: { value?, label }[]
featurestitle?, lead?, items: Feature[]
showcasetitle?, lead?, tabs: ShowcaseTab[]
embedtitle?, description?, media: MediaRef
useCasestitle?, lead?, items: UseCaseItem[]
linkstitle?, lead?, items: LinkItem[]
benefitstitle?, lead?, items: BenefitItem[]
specstitle?, lead?, rows: { label, value }[]
ctatitle, description?, ctas?

MediaRef is { kind: "image" | "video" | "component", src?, alt?, componentId? }.

When kind === "component", componentId names a consumer-side React

component (e.g. "schemaBuilderPart1") — the API does not ship binary

payloads.

The authoritative TypeScript definitions live at

[shared/solutions.ts](https://github.com/synerise/website) and are

re-exported from the public @synerise/solutions-types package (planned).

Errors

StatusBodyMeaning
404{ "error": "not_found" }Unknown slug or section id
429{ "error": "rate_limited" }Per-IP rate limit exceeded

Source of truth

Each page's content is the source of truth: solutionContent is

co-located with the React page at

client/src/pages/solutions/<slug>.tsx. The build extracts the literal at

deploy time into build/solutions/<slug>.json. The runtime falls back to

live extraction in development so the API works without running the build

step.

Changelog

schemaVersion: 1.