- SDK
- Documents
SDK
Documents
Upload, list, poll, and delete documents. Query their contents with RAG.
Overview
Upload documents to provide context for your assistant via RAG. Documents can be scoped to an assistant (shared across all threads) or a thread (single conversation).
Documents are persistent — once uploaded, they stay attached until deleted. This is different from per-turn parameters like tools or system_prompt.
Supported file types: .pdf, .doc(x), .ppt(x), .xls(x), .txt, .csv, .md, .json(l), .xml, .py, .js, .ts, .jsx, .tsx, .html, .css, .cpp, .c, .h, .java, .go, .rs, .rb, .php, .sql, .png, .jpg, .jpeg, .webp, .gif, .bmp, .tiff
Upload to Assistant (shared context)
Documents uploaded to an assistant are available across all threads under that assistant:
Python
JavaScript
TypeScript
import asyncio
from backboard import BackboardClient
async def main():
client = BackboardClient(api_key="YOUR_API_KEY")
assistant = await client.create_assistant(
name="Document Assistant",
system_prompt="You are a helpful document analysis assistant"
)
document = await client.upload_document_to_assistant(
assistant.assistant_id,
"knowledge-base.pdf"
)
print(f"Uploaded: {document.document_id} — status: {document.status}")
if __name__ == "__main__":
asyncio.run(main())
Upload to Thread (conversation-specific)
Use the thread_id from a previous send_message response:
Python
JavaScript
TypeScript
document = await client.upload_document_to_thread(
thread_id,
"meeting-notes.pdf"
)
Poll Document Status
Documents must reach indexed status before they’re available for RAG. Status values: pending → processing → indexed (or error).
Python
JavaScript
TypeScript
while True:
status = await client.get_document_status(document.document_id)
print(f"Status: {status.status}")
if status.status == "indexed":
print(f"Ready! Chunks: {status.chunk_count}, Tokens: {status.total_tokens}")
break
elif status.status == "error":
print(f"Error: {status.status_message}")
break
await asyncio.sleep(2)
Query Documents (Non-Streaming)
Pass assistant_id to query that assistant’s documents. No need to create a thread first — send_message auto-creates one:
Python
JavaScript
TypeScript
response = await client.send_message(
"What are the key points in the uploaded document?",
assistant_id=assistant.assistant_id,
)
print(response.content)
print(f"Files used: {response.retrieved_files_count}")
print(f"thread_id: {response.thread_id}")
Query Documents (Streaming)
Python
JavaScript
TypeScript
async for chunk in await client.send_message(
"Summarize the document",
assistant_id=assistant.assistant_id,
stream=True,
):
if chunk.get("type") == "content_streaming":
print(chunk.get("content", ""), end="", flush=True)
print()
List Documents
Python
JavaScript
TypeScript
docs = await client.list_assistant_documents(assistant.assistant_id)
for doc in docs:
print(f"{doc.filename} — {doc.status}")
thread_docs = await client.list_thread_documents(thread_id)
Delete a Document
Python
JavaScript
TypeScript
result = await client.delete_document(document.document_id)