Documentation Index Fetch the complete documentation index at: https://docs.chatgrid.ai/llms.txt
Use this file to discover all available pages before exploring further.
What you’ll build
A research synthesis board that ingests multiple documents, finds cross-cutting themes, and creates a visual map linking findings to source material.
Upload and vectorize 5+ PDFs
Ask AI to identify themes across all sources
Create finding nodes connected to source documents
Search for specific topics across your entire document set
Prerequisites
ChatGrid API key (get one here )
Node.js 18+ or Python 3.10+
PDF files or document URLs to analyze
Step 1: Create a research board
curl -X POST https://api.chatgrid.ai/v1/boards \
-H "Authorization: Bearer cgk_live_..." \
-H "Content-Type: application/json" \
-d '{"name": "Q1 Market Research Synthesis"}'
Step 2: Upload PDFs and create document nodes
Upload each PDF as an asset, then create a node on the canvas.
# Upload the file
curl -X POST https://api.chatgrid.ai/v1/boards/{boardId}/assets \
-H "Authorization: Bearer cgk_live_..." \
-F "file=@gartner-report-2026.pdf"
# Create a PDF node (use the asset URL from the upload response)
curl -X POST https://api.chatgrid.ai/v1/boards/{boardId}/nodes \
-H "Authorization: Bearer cgk_live_..." \
-H "Content-Type: application/json" \
-d '{"type": "pdf", "position": {"x": 0, "y": 0}, "data": {"label": "Gartner Report 2026", "url": "{assetUrl}"}}'
Repeat for all documents. Here is how to batch it in Python:
documents = [
{ "file" : "gartner-report-2026.pdf" , "label" : "Gartner Report" , "x" : 0 },
{ "file" : "forrester-wave-q1.pdf" , "label" : "Forrester Wave Q1" , "x" : 400 },
{ "file" : "internal-survey.pdf" , "label" : "Customer Survey" , "x" : 800 },
{ "file" : "competitor-teardown.pdf" , "label" : "Competitor Teardown" , "x" : 0 , "y" : 350 },
{ "file" : "win-loss-analysis.pdf" , "label" : "Win/Loss Analysis" , "x" : 400 , "y" : 350 },
]
node_ids = []
for doc in documents:
with open (doc[ "file" ], "rb" ) as f:
upload = requests.post( f " { BASE } /boards/ { board_id } /assets" ,
headers = { "Authorization" : f "Bearer { API_KEY } " }, files = { "file" : f})
asset_url = upload.json()[ "data" ][ "url" ]
node = requests.post( f " { BASE } /boards/ { board_id } /nodes" , headers = headers, json = {
"type" : "pdf" , "position" : { "x" : doc[ "x" ], "y" : doc.get( "y" , 0 )},
"data" : { "label" : doc[ "label" ], "url" : asset_url},
})
node_ids.append({ "id" : node.json()[ "data" ][ "id" ], "label" : doc[ "label" ]})
Step 3: Vectorize all documents
Vectorize each document’s content, linking chunks to the source node.
curl -X POST https://api.chatgrid.ai/v1/boards/{boardId}/documents/vectorize \
-H "Authorization: Bearer cgk_live_..." \
-H "Content-Type: application/json" \
-d '{"url": "{assetUrl}", "node_id": "{nodeId}", "metadata": {"source": "gartner-report-2026.pdf"}}'
# Repeat for each document
Large PDFs (50+ pages) may take 30-60 seconds. ChatGrid extracts text from scanned pages via OCR automatically.
Step 4: Ask AI to find themes
Create a chat and ask the AI to synthesize across all documents.
curl -X POST https://api.chatgrid.ai/v1/boards/{boardId}/chats \
-H "Authorization: Bearer cgk_live_..." \
-H "Content-Type: application/json" \
-d '{"title": "Cross-Document Synthesis"}'
curl -X POST https://api.chatgrid.ai/v1/boards/{boardId}/chats/{chatId}/messages \
-H "Authorization: Bearer cgk_live_..." \
-H "Content-Type: application/json" \
-d '{
"content": "Analyze all documents on this board. Identify the top 5 recurring themes. For each theme, cite which documents mention it and summarize the key points.",
"stream": false
}'
Step 5: Create finding nodes and connect to sources
Turn each theme into a sticky note and draw edges to the documents it references.
themes = [
{ "label" : "AI adoption accelerating" , "content" : "3 of 5 reports cite >40% YoY growth in AI tool adoption." , "sources" : [node_ids[ 0 ], node_ids[ 1 ]], "x" : 200 },
{ "label" : "Buyer consolidation" , "content" : "Teams reducing vendor count from 8 to 3." , "sources" : [node_ids[ 1 ], node_ids[ 4 ]], "x" : 600 },
{ "label" : "Self-serve preferred" , "content" : "72% prefer self-serve onboarding." , "sources" : [node_ids[ 2 ], node_ids[ 4 ]], "x" : 1000 },
]
for theme in themes:
node = requests.post( f " { BASE } /boards/ { board_id } /nodes" , headers = headers, json = {
"type" : "sticky_note" , "position" : { "x" : theme[ "x" ], "y" : 700 },
"data" : { "label" : f "Theme: { theme[ 'label' ] } " , "content" : theme[ "content" ]},
})
finding_id = node.json()[ "data" ][ "id" ]
for source in theme[ "sources" ]:
requests.post( f " { BASE } /boards/ { board_id } /edges" , headers = headers, json = {
"source_node_id" : finding_id, "target_node_id" : source[ "id" ], "data" : { "label" : "cited in" },
})
Step 6: Search for specific topics
Query across all documents without re-reading them.
curl -X POST https://api.chatgrid.ai/v1/boards/{boardId}/documents/search \
-H "Authorization: Bearer cgk_live_..." \
-H "Content-Type: application/json" \
-d '{"query": "what do analysts say about pricing pressure in 2026?", "limit": 5}'
Results include matching text, similarity score, and source metadata so you can trace every finding back to its document.
What’s happening under the hood
Each uploaded PDF goes through text extraction (with OCR for scanned pages), chunking into ~500-token segments with overlap, and embedding via pgvector. The node_id parameter ties chunks to their visual node, so edges between finding nodes and source nodes are meaningful. When AI answers a synthesis question, it performs semantic search across all chunks on the board and reasons over the top matches. The metadata you attach appears in search results, making claims easy to verify.
Next steps
Meeting Knowledge Turn meeting notes into searchable knowledge
Competitive Intel Track competitor websites and compare positioning