Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.outkit.dev/llms.txt

Use this file to discover all available pages before exploring further.

The core endpoint. Sends raw AI text and receives structured ContentBlock[] — tables, charts, alerts, checklists, and more.

Request

content
string
required
The full AI text response to enhance. Can include markdown formatting.
context
string
The user’s original prompt or conversation context. Improves classification accuracy — helps distinguish, for example, a comparison table from raw data.
preferences
object
Optional hints to control enhancement behavior.
stream
boolean
default:"true"
When true (default), returns Server-Sent Events (SSE). When false, returns a single JSON response after processing completes.

Response (JSON mode)

Set ?stream=false to get a single JSON response:
curl -X POST "https://api.outkit.dev/render/enhance?stream=false" \
  -H "Content-Type: application/json" \
  -H "x-outkit-api-key: your-api-key" \
  -d '{
    "content": "Here are the top 3 frameworks:\n\n| Framework | Stars | Language |\n|-----------|-------|----------|\n| React | 220k | JavaScript |\n| Vue | 207k | JavaScript |\n| Svelte | 78k | JavaScript |\n\n**Tip:** Svelte has the smallest bundle size.",
    "context": "User asked about frontend frameworks"
  }'

Response Body

{
  "blocks": [
    {
      "component": "text",
      "version": "1.0",
      "props": {
        "content": "Here are the top 3 frameworks:",
        "variant": "prose"
      }
    },
    {
      "component": "table",
      "version": "1.0",
      "props": {
        "columns": ["Framework", "Stars", "Language"],
        "rows": [
          { "Framework": "React", "Stars": "220k", "Language": "JavaScript" },
          { "Framework": "Vue", "Stars": "207k", "Language": "JavaScript" },
          { "Framework": "Svelte", "Stars": "78k", "Language": "JavaScript" }
        ],
        "sortable": true
      },
      "meta": { "confidence": 0.95 },
      "fallback": "| Framework | Stars | Language |..."
    },
    {
      "component": "alert",
      "version": "1.0",
      "props": {
        "variant": "tip",
        "message": "Svelte has the smallest bundle size."
      },
      "meta": { "confidence": 0.90 }
    }
  ],
  "debug": {
    "componentsDetected": 2,
    "processingTimeMs": 1850,
    "provider": "gemini",
    "classifications": [
      { "component": "table", "confidence": 0.95, "sourceRange": [0, 0] },
      { "component": "alert", "confidence": 0.90, "sourceRange": [0, 0] }
    ]
  },
  "design": {
    "--outkit-primary": "#b30069",
    "--outkit-bg": "#fbf9f8",
    "--outkit-text": "#1b1c1c"
  }
}
The design field contains CSS custom properties from the design profile linked to your API key. Use these tokens to style rendered components consistently with your brand.

Wire Format

The raw API response uses compact single-character keys for bandwidth efficiency:
Wire keyExpanded keyDescription
ccomponentComponent type key
vversionSpec version
ppropsComponent-specific data
mmetaOptional metadata (confidence, title)
ffallbackFallback markdown text
The @outkit-dev/react SDK expands wire format automatically. If you integrate directly, you’ll receive the wire format. The examples in these docs show the expanded format for readability.

Response (Streaming mode)

With streaming enabled (the default), the response is delivered as Server-Sent Events:
curl -X POST "https://api.outkit.dev/render/enhance" \
  -H "Content-Type: application/json" \
  -H "x-outkit-api-key: your-api-key" \
  -d '{ "content": "..." }'
data: {"type":"meta","design":{"--outkit-primary":"#b30069","--outkit-bg":"#fbf9f8"}}

data: {"component":"text","version":"1.0","props":{"content":"Here are the top 3 frameworks:","variant":"prose"}}

data: {"component":"table","version":"1.0","props":{...}}

data: {"component":"alert","version":"1.0","props":{...}}

data: [DONE]
The first event is always a meta event containing design tokens for your profile. Component blocks follow in document order — text content arrives as component: "text" blocks, same as any other component. The stream ends with data: [DONE].
Filter out meta events before rendering — they contain configuration data, not content blocks.

Why Streaming?

Streaming lets you render content progressively as the LLM generates it:
  1. meta event arrives → apply design tokens to your renderer
  2. LLM token chunks arrive → the SDK parses structured blocks incrementally
  3. [DONE] signals the stream is complete
The @outkit-dev/react SDK handles this automatically via feedChunk / feedMeta / feedDone — it accumulates raw chunks, parses partial JSON into renderable blocks, and shows skeleton placeholders while waiting for each component to complete. See the React SDK guide for the full integration pattern.
Your API key must stay on your server. Your backend should proxy the SSE stream to the browser — the React SDK handles parsing on the client side.

ContentBlock Schema

Every response contains an ordered array of blocks. See ContentBlock reference for the full schema of each block type.

Code Examples

JSON Mode

import requests

response = requests.post(
    "https://api.outkit.dev/render/enhance",
    params={"stream": "false"},
    headers={
        "Content-Type": "application/json",
        "x-outkit-api-key": "your-api-key",
    },
    json={
        "content": ai_response_text,
        "context": user_prompt,
    },
)

data = response.json()
design = data.get("design", {})  # CSS custom properties for styling

for block in data["blocks"]:
    if block.get("c"):  # wire format component block
        render_component(block["c"], block["p"])

Streaming Mode

import requests

response = requests.post(
    "https://api.outkit.dev/render/enhance",
    headers={
        "Content-Type": "application/json",
        "x-outkit-api-key": "your-api-key",
    },
    json={"content": ai_response_text},
    stream=True,
)

for line in response.iter_lines():
    line = line.decode("utf-8")
    if not line.startswith("data: "):
        continue
    data = line[6:]
    if data == "[DONE]":
        break

    import json
    block = json.loads(data)

    if block.get("type") == "meta":
        design_tokens = block.get("design", {})
        continue  # not a content block

    # Handle content blocks...

Quota Exhausted (Passthrough Mode)

When your monthly render quota is exhausted, the API returns your original content as a single text component block instead of returning an error. The response includes mode: "passthrough" in the debug metadata:
{
  "blocks": [
    { "component": "text", "version": "1.0", "props": { "content": "...your original content unchanged...", "variant": "prose" } }
  ],
  "debug": {
    "mode": "passthrough",
    "componentsDetected": 0,
    "processingTimeMs": 0
  }
}
Your application should handle passthrough gracefully — for example, by rendering the text as markdown. The @outkit-dev/react SDK handles this automatically.