#1 on DeepSearchQA — by 8 points.

Spine Deep Research scores 87.6% on DeepSearchQA, ahead of Perplexity (79.5%), Claude (76.1%), ChatGPT (71.3%), and Gemini Deep Research (66.1%) on the same public eval.

Read the benchmark write-up

How it works

1. Start a run via REST

POST a prompt (and an optional template — slides, deep_research, report, excel, memo, app, landing_page) to /v1/run. You get a run_id back immediately — no long-lived connection required.

2. Async by design

One POST kicks off the agent swarm; webhook callbacks notify your app the moment results are ready.

3. Receive polished deliverables

Download .pptx decks, .docx briefs, Excel models with formulas, images, JSON research reports with citations, or interactive dashboards — whatever the task called for.

Works inside every agentic surface

Spine is a REST API, not a framework. Call it from any coding agent, IDE, or chat.

  • Claude — Turn any Claude turn into a 50-page investment memo or a 30-slide deck — not just a message.
  • Cursor — Cursor agents ship research memos, decks, and spreadsheets from a rule file — not just code.
  • Replit — Replit apps pull real research and client-ready artifacts inline — no more placeholder content.
  • Codex — Give the Codex CLI long-running research agents and polished deliverables behind one REST call.
  • Lovable — Lovable apps produce real investor decks, market memos, and research reports for end users.
  • OpenClaw — OpenClaw agents ship real research briefs, decks, and spreadsheets — not just local-system actions.
  • Hermes — Hermes agents send polished client deliverables as fast as they send messages.

Agent integration guide: https://docs.getspine.ai/api-reference/for-agents

Every task is fully auditable

Spine returns a step-by-step trace of every agent action, sub-task dispatched, and intermediary output produced. Debug runs, cite sources, or show your work to clients — nothing is a black box.

  • Every agent dispatch and tool call is logged with timing and tokens.
  • Intermediary outputs (outlines, research notes, drafts) are retrievable via GET /v1/canvas/{id}/tasks.
  • Ship deliverables alongside their sources — no black boxes.

Example task tree

  • Morning Brief: Axios + Mercor + Claude leak coverage [task]
    • Axios Attacks Researcher [persona]
      • Create Plan Note [agent]
      • Research: Supply-chain Attack Vectors [agent]
        • axios-research-block[block]
    • Morning Brief Synthesizer [persona]
      • Compose Exec Memo [agent]
        • synthesis-memo-block[block]
      • Render Dashboard [agent]
        • deck.pptx[block]

The same run is also visualised as a canvas DAG at GET /v1/canvas/{id}/dag: 7 nodes, 6 edges — each edge represents a dependency between blocks.

REST endpoints

Small surface area. Full reference at docs.getspine.ai.

Method Path Purpose
POST /v1/run Start an async run (multipart form). Returns a run_id immediately.
GET /v1/run/{run_id} Poll status, retrieve final output and downloadable artifacts.
GET /v1/canvas/{id}/dag Block graph (nodes and edges) for the canvas this run produced.
GET /v1/canvas/{id}/tasks Task tree — every agent action, sub-task, and intermediary output.

Submit a task (curl)

# 1. Start a run
curl -X POST https://api.getspine.ai/v1/run \
  -H "X-API-KEY: $SPINE_API_KEY" \
  -F 'prompt=Build an investor-ready competitive analysis for the AI coding assistants space.' \
  -F 'template=slides'
# → { "data": { "run_id": "uuid", "status": "running" } }

# 2. Poll until done
curl https://api.getspine.ai/v1/run/<run_id> \
  -H "X-API-KEY: $SPINE_API_KEY"
# → { "data": { "status": "completed",
#     "result": { "final_output": "...",
#       "artifacts": [{ "name": "deck.pptx", "download_url": "..." }] } } }

JavaScript (fetch)

const form = new FormData();
form.append("prompt", "Build an investor-ready competitive analysis for the AI coding assistants space.");
form.append("template", "slides");

const res = await fetch("https://api.getspine.ai/v1/run", {
  method: "POST",
  headers: { "X-API-KEY": process.env.SPINE_API_KEY },
  body: form,
});
const { data } = await res.json();
const runId = data.run_id;

// Poll until done
while (true) {
  const r = await fetch(`https://api.getspine.ai/v1/run/${runId}`, {
    headers: { "X-API-KEY": process.env.SPINE_API_KEY },
  });
  const { data: run } = await r.json();
  if (["completed", "partial", "failed"].includes(run.status)) break;
  await new Promise((res) => setTimeout(res, 5_000));
}

Python (httpx)

import os, time, httpx

API_KEY = os.environ["SPINE_API_KEY"]
BASE = "https://api.getspine.ai"
H = {"X-API-KEY": API_KEY}

r = httpx.post(f"{BASE}/v1/run", headers=H,
               data={"prompt": "Build an investor-ready competitive analysis for the AI coding assistants space.",
                     "template": "slides"})
run_id = r.json()["data"]["run_id"]

while True:
    run = httpx.get(f"{BASE}/v1/run/{run_id}", headers=H).json()["data"]
    if run["status"] in ("completed", "partial", "failed"):
        break
    time.sleep(5)

for a in run["result"]["artifacts"]:
    print(a["name"], "→", a["download_url"])

Pay as you go. No subscriptions.

  • $1 = 1,000 credits
  • $10 free to try

Sign up at platform.getspine.ai and get $10 in free credits on us — enough to run several real tasks. No subscriptions, no seats, no monthly minimums.

Docs

Full request/response schemas, deliverable formats, and error codes: docs.getspine.ai.


API Reference

Base URL: https://api.getspine.ai

Authentication

All endpoints require an X-API-KEY header. Get a key from the Spine dashboard → Settings → Developer Keys. Keys can be rotated or revoked at any time.

X-API-KEY: sk_spine_...

Start a run — request parameters

POST /v1/run accepts a multipart/form-data body with the following fields:

Field Required Type Description
prompt yes string Natural-language description of what to produce.
template no string One of: auto, deep_research, report, slides, memo, excel, app, landing_page. Defaults to 'auto'.
blocks no JSON array Advanced: pass an explicit array of block definitions to override the template.

Templates

Pass one of the following template values, or pass blocks (a JSON array) for finer control.

id what it does output
auto Let Spine pick blocks based on the prompt Varies
deep_research Multi-source research with citations Memo (.docx)
report Structured report with sections Report (.docx)
slides Presentation deck Slides (.pptx)
memo Short executive memo Memo (.docx)
excel Spreadsheet analysis Workbook (.xlsx)
app Single-page web app App (.html)
landing_page Marketing landing page Page (.html)

Block types (for blocks override)

prompt-block, list-block, memo-block, document-block, excel-block, deep-research-block, image-block, presentation-block, app-block, table-block, prototype-block, landing-page-block, text-block, web-block, yt-block, web-research-block, file-block.

Response shapes

Run just started:

{
  "data": {
    "run_id": "01HXZJ4P...K3Q9",
    "status": "running"
  }
}

Run completed:

{
  "data": {
    "status": "completed",
    "result": {
      "final_output": "<summary text>",
      "artifacts": [\
        { "name": "deck.pptx", "download_url": "https://..." }\
      ]
    }
  }
}

Terminal statuses: completed, partial, failed. Non-terminal: queued, running.

Full polling loop (Python)

import os, time, httpx

API_KEY = os.environ["SPINE_API_KEY"]
BASE = "https://api.getspine.ai"
H = {"X-API-KEY": API_KEY}

def run(prompt, template="auto", **kwargs):
    r = httpx.post(f"{BASE}/v1/run", headers=H,
                   data={"prompt": prompt, "template": template, **kwargs})
    run_id = r.json()["data"]["run_id"]

while True:
        p = httpx.get(f"{BASE}/v1/run/{run_id}", headers=H).json()["data"]
        if p["status"] in ("completed", "partial", "failed"):
            return p
        time.sleep(5)

result = run("Build a landing page for an AI sales tool", template="landing_page")
print(result["result"]["final_output"])
for a in result["result"]["artifacts"]:
    print(a["name"], "→", a["download_url"])

Use as a tool inside Claude / Anthropic SDK

// Use Spine as a tool inside the Anthropic SDK
import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();
const tool = {
  name: "spine_run",
  description: "Spawn a multi-agent Spine run that produces research, memos, decks, excel, or apps.",
  input_schema: {
    type: "object",
    properties: {
      prompt: { type: "string" },
      template: {
        type: "string",
        enum: ["auto", "deep_research", "report", "slides", "memo", "excel", "app", "landing_page"],
      },
    },
    required: ["prompt"],
  },
};

const resp = await client.messages.create({
  model: "claude-sonnet-4-5",
  max_tokens: 2048,
  tools: [tool],
  messages: [{ role: "user", content: "Make a market report on AI agents" }],
});
// On stop_reason="tool_use" → POST /v1/run, poll GET /v1/run/{run_id}, feed result back.

Errors

Errors return {"success": false, "error": "..."} with one of these HTTP codes:

Code Reason
400 Bad template, malformed blocks, or invalid UUID.
401 Missing or invalid X-API-KEY.
404 Run or canvas not found (or not owned by the authenticated key).
500 Server error — retry with exponential backoff.