Skip to content

Ingest uploaded documents as the pack's next immutable version

POST
/v1/knowledge-packs/{pack_id}/documents
curl --request POST \
--url https://api.vocapable.com/v1/knowledge-packs/example/documents \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "documents": [ { "file_name": "example", "content": "example", "content_base64": "example", "format": "pdf" } ], "budget_tokens": 1 }'

Upload pdf/docx/csv/md/txt and publish the extraction as the next version.

Everything that can refuse the upload - decoding, extraction, sectioning, the real token count, the hard cap - runs first and touches no database. Only a pack that has already compiled inside the cap reaches create_version, which re-checks the cap itself before its own first statement. The ordering CANON fact 12 depends on therefore holds twice over: an over-cap upload consumes no version number and writes nothing.

pack_id
required
Pack Id
string
Media typeapplication/json
KnowledgePackIngestRequest

POST /v1/knowledge-packs/{id}/documents - upload documents as the next version.

budget_tokens is the caller’s own ceiling, not the platform’s. The 16,000-token hard cap (docs/08-ai-quality.md, CANON fact 12) always applies and bounds this field; leaving it unset means only the hard cap is enforced, which is exactly what the hand-authored version endpoint does.

object
documents
required
Documents
Array<object>
>= 1 items <= 20 items
KnowledgePackDocumentUpload

One uploaded file.

The bytes arrive base64-encoded (content_base64) or, for the three text formats, as plain text (content) - never as multipart/form-data, which needs python-multipart and is not a workspace dependency. ContactImportRequest made the same call for CSV uploads, and the extractor takes bytes either way, so the wire shape can change later without touching ingestion.

object
file_name
required
File Name
string
>= 1 characters <= 255 characters
content
Any of:
string
>= 1 characters
content_base64
Any of:
string
>= 1 characters
format
Any of:
string
Allowed values: pdf docx csv md txt
budget_tokens
Any of:
integer
>= 1 <= 16000

Successful Response

Media typeapplication/json
KnowledgePackIngestResponse

The created version plus the ingest accounting behind it.

object
version
required
KnowledgePackVersionResource

A compiled version. Immutable once ready - an edit is the next version.

object
id
required
Id
string
knowledge_pack_id
required
Knowledge Pack Id
string
version
required
Version
integer
content_hash
required
Content Hash
string
compiled_token_count
Any of:
integer
status
required
Status
string
Allowed values: compiling ready failed
sources
required
Sources
Array<object>
PackSource

One distilled section of a pack, plus where it came from.

text is the artifact, not a summary of one: knowledge_pack_versions carries sources and no separate body column, so these sections are the compiled pack. Phrase them spoken-answer-ready - short declaratives an agent can say verbatim.

object
kind
required
Kind
string
Allowed values: pdf url text
label
required
Label
string
>= 1 characters <= 200 characters
text
required
Text
string
>= 1 characters
uri
Any of:
string
created_at
required
Created At
string format: date-time
updated_at
required
Updated At
string format: date-time
over_default_budget
required
Over Default Budget

Compiled above the 8k default budget but inside the 16k hard cap.

Permitted, and worth telling the tenant: a cap-size pack roughly doubles cold prefill and halves the number of warm pack prefixes a node holds.

boolean
documents
required
Documents
Array<object>
IngestedDocumentReport

What one uploaded document cost, so “distill harder” names a file.

The parts need not sum to the version’s compiled_token_count: a BPE tokenizer merges across the joins between documents, so the pack is counted once as a whole.

object
file_name
required
File Name
string
format
required
Format
string
sections
required
Sections
integer
tokens
required
Tokens
integer
Example
{
"version": {
"status": "compiling",
"sources": [
{
"kind": "pdf"
}
]
}
}

Validation Error

Media typeapplication/json
HTTPValidationError
object
detail
Detail
Array<object>
ValidationError
object
loc
required
Location
Array
msg
required
Message
string
type
required
Error Type
string
input
Input
ctx
Context
object
Examplegenerated
{
"detail": [
{
"loc": [
"example"
],
"msg": "example",
"type": "example",
"input": "example",
"ctx": {}
}
]
}