Create Document By Text API#
Overview#
The Create Document By Text endpoint (POST /datasets/{dataset_id}/document/create-by-text) ingests raw text as a document into a Dify knowledge base. The request body is validated by DocumentTextCreatePayload, the document creation is asynchronous, and the response includes a batch ID for polling indexing status.
Canonical path: /datasets/{dataset_id}/document/create-by-text
Deprecated alias: /datasets/{dataset_id}/document/create_by_text (underscore form β kept for backward compatibility)
Both paths share the same handler: _create_document_by_text.
Request Fields (DocumentTextCreatePayload)#
Defined in document.py:
| Field | Type | Required | Notes |
|---|---|---|---|
name | str | Yes | Document name |
text | str | Yes | Raw text content |
indexing_technique | "high_quality" | "economy" | null | Conditional | See below |
doc_form | "text_model" | "hierarchical_model" | "qa_model" | No | Default: "text_model" |
doc_language | str | No | Default: "English" |
process_rule | ProcessRule | No | If omitted, inherits the dataset's latest rule |
retrieval_model | RetrievalModel | No | Search/ranking config |
embedding_model | str | No | Must pair with embedding_model_provider |
embedding_model_provider | str | No | Must pair with embedding_model |
original_document_id | str | No | Set to replace an existing document |
indexing_technique Validation Logic#
indexing_technique is conditionally required β not statically required in the Pydantic schema. The runtime check lives in _create_document_by_text:
if not dataset.indexing_technique and not args.get("indexing_technique"):
raise ValueError("indexing_technique is required.")
In plain terms:
- First document into a new knowledge base (no
indexing_techniqueset on the dataset yet): you must supplyindexing_technique. - Subsequent documents in a knowledge base that already has an indexing technique: the field is optional; the dataset's existing value is used.
The two accepted string values are "high_quality" (embedding-based) and "economy" (keyword-based). The type annotation IndexingTechnique is str | None with a JSON Schema anyOf expressing those two values, but the conditional requirement is not enforceable in OpenAPI β it is enforced at runtime only.
At the KnowledgeConfig level, indexing_technique is typed as Literal["high_quality", "economy"] (non-nullable, required). The nullable str | None in DocumentTextCreatePayload is a deliberate relaxation to accommodate the "inherit from dataset" case; the value is populated before KnowledgeConfig is instantiated.
Other Conditional Field Rules#
embedding_model/embedding_model_provider: Must be provided together. If both are present,DatasetService.check_embedding_model_settingis called to validate the model against available providers.retrieval_model.reranking_model: If a reranking model is supplied (bothreranking_provider_nameandreranking_model_name),DatasetService.check_reranking_model_settingvalidates it.process_rule: If omitted, the dataset's latest process rule is applied automatically . Omittingprocess_ruleon a brand-new dataset (no prior rule) will result inNonebeing passed, which may fail downstream.
OpenAPI / Schema Limitations#
OpenAPI 3.x oneOf/anyOf can partially express conditional requirements, but the indexing_technique dependency on dataset state (a server-side condition) cannot be expressed in a static schema at all. The field is documented as optional (default: null) in DocumentTextCreatePayload , with a prose description explaining the rule.
The same issue applies to the embedding_model β embedding_model_provider pairing: static schemas cannot express "both or neither" constraints tied to each other β these are enforced at runtime only.
For DocumentTextUpdate (the update variant), there is a custom __get_pydantic_json_schema__ that emits an anyOf with two branches β one requiring both name and text (non-null), one allowing text to be null β to partially express the name is required when text is provided rule. The same pattern could theoretically be applied to create, but the dataset-state dependency makes it impractical.
Response#
Returns DocumentAndBatchResponse:
{
"document": { ... },
"batch": "<batch_id>"
}
Use batch with GET /datasets/{dataset_id}/documents/{batch}/indexing-status to track progress through: waiting β parsing β cleaning β splitting β indexing β completed .
Related Entry Points#
| What | Where |
|---|---|
| Request payload model | DocumentTextCreatePayload |
| Core handler | _create_document_by_text |
| Canonical route class | DocumentAddByTextApi |
| Downstream config model | KnowledgeConfig |
IndexingTechnique type | knowledge_entities.py:16-19 |
ProcessRule type | knowledge_entities.py:128-135 |
| Text update variant | DocumentTextUpdate / _update_document_by_text |
| Knowledge API guide | en/api-reference/guides/knowledge.mdx |