Annotated Document Import

March 22, 2026 ยท View on GitHub

The annotated document import lets you add a single document with pre-built annotations directly into an existing corpus. This is useful for programmatic workflows where an external tool has already analyzed a document and produced annotation data.

GraphQL Mutation

Mutation: UploadAnnotatedDocument

ParameterTypeRequiredDescription
targetCorpusIdIDYesCorpus to import into
documentImportDataStringYesJSON string matching the import schema below

The import runs asynchronously via a Celery task (import_document_to_corpus).

Import Data Schema

The documentImportData JSON string must conform to the OpenContractsAnnotatedDocumentImportType structure:

FieldTypeDescription
doc_dataobjectDocument export data (same structure as a single entry in annotated_docs from a corpus export)
pdf_base64stringBase64-encoded document file content
pdf_namestringFilename for the document
doc_labelsmapDocument-level label definitions keyed by label name
text_labelsmapText annotation label definitions keyed by label name
relationshipslist (optional)Annotation-to-annotation relationships

The doc_data Object

This follows the same OpenContractDocExport structure used in corpus exports:

FieldTypeDescription
titlestringDocument title
contentstringFull extracted text
descriptionstring or nullDocument description
page_countintNumber of pages
pawls_file_contentlistPAWLs token data (can be empty for text documents)
doc_labelslist of stringsDocument label names to apply
labelled_textlistText annotations (see below)
structuralboolWhether this contains structural annotations

Annotations in labelled_text

Each annotation follows the standard annotation format:

FieldTypeDescription
idstring/int/nullLocal ID for cross-referencing within the import
annotationLabelstringLabel name (must exist in the text_labels map)
rawTextstringThe annotated text
pageint0-based page index
annotation_jsonobjectPositional data (token refs for PDFs, character offsets for text)
parent_idstring/int/nullID of parent annotation (for hierarchical annotations)
annotation_typestring or null"TOKEN_LABEL" or "SPAN_LABEL"
structuralboolWhether this is a structural annotation
long_descriptionstring or nullMarkdown description (used for document index entries)

Import Process

  1. The document file is decoded from base64 and stored
  2. Labels are created or matched to existing labels in the corpus's label set
  3. The document record is created with extracted text and PAWLs data
  4. Annotations are created in two passes:
    • First pass: Create all annotation records, building an ID mapping from import-local IDs to new database IDs
    • Second pass: Wire up parent FK relationships using the ID mapping
  5. Relationships between annotations are created using the remapped IDs
  6. The document is added to the corpus

Use Cases

  • External NLP pipelines: Run annotation models outside OpenContracts and import the results
  • Data migration: Move annotated documents from another system
  • Programmatic index building: Create documents with OC_SECTION annotations for navigable document indexes (see Annotation Side Effects)
  • Batch annotation: Pre-annotate documents before human review

Relation to Corpus Export Format

The annotated document import schema is intentionally compatible with the corpus export format. A single entry from a corpus export's annotated_docs map can be used directly as the doc_data field, making it straightforward to extract individual documents from an export and re-import them elsewhere.

For the full annotation format specification, see the Corpus Export Format Specification.