Skip to main content

Export & Import API

Export and import all user-created data in JSON Lines format with conflict resolution. Supports annotations, personas, ontologies, world state objects, summaries, and claims.

Supported Data Types

The export/import system supports all user-created data types:

Data TypeExport EndpointDescription
Personas/api/export/personasUser personas with roles and information needs
Ontologies/api/export/personasType definitions (entity, event, role, relation types)
World State/api/export/worldEntities, events, times, locations, collections, relations
Summaries/api/export/summariesVideo summaries with claims
Claims/api/export/summariesExtracted claims from summaries
Claim Relations/api/export/summariesRelationships between claims
Annotations/api/exportBounding box annotations
All Data/api/export/allComplete data export

Export Annotations

Export annotations with bounding box sequences in JSON Lines format.

Request

GET /api/export

Query Parameters

ParameterTypeRequiredDescription
formatstringNoExport format: "jsonl" or "json" (default: "jsonl")
includeInterpolatedbooleanNoInclude all interpolated frames (default: false)
personaIdsstringNoComma-separated persona UUIDs to filter
videoIdsstringNoComma-separated video IDs to filter
annotationTypesstringNoComma-separated types: "type", "object"

Response

Status: 200 OK

Content-Type: application/x-ndjson (for jsonl) or application/json (for json)

Content-Disposition: attachment; filename="annotations.jsonl"

Custom Headers:

  • X-Export-Size: Export size in MB
  • X-Export-Annotations: Number of annotations
  • X-Export-Sequences: Number of sequences
  • X-Export-Keyframes: Number of keyframes
  • X-Export-Interpolated-Frames: Number of interpolated frames
  • X-Export-Warning: Warning message (if export is large)

JSON Lines format (one annotation per line):

{"id":"550e8400-e29b-41d4-a716-446655440000","videoId":"abc123def456","personaId":"660e8400-e29b-41d4-a716-446655440001","annotationType":"type","typeAssignment":{"typeId":"entity-001","typeName":"Pitcher"},"boundingBoxSequence":{"interpolationMode":"linear","boxes":[{"frameNumber":0,"x":100,"y":100,"width":200,"height":150,"isKeyframe":true,"visible":true}]},"createdAt":"2025-10-06T14:30:00.000Z","updatedAt":"2025-10-06T14:30:00.000Z"}

Status: 400 Bad Request

{
"error": "Validation failed",
"message": "Some annotations have invalid sequences",
"validationErrors": [
{
"annotationId": "550e8400-e29b-41d4-a716-446655440000",
"errors": [
"Sequence must have at least one keyframe",
"Frame numbers must be in ascending order"
]
}
]
}

Export Modes

Keyframes-Only Mode (default)

Exports only keyframes. Interpolated frames are not included.

curl "http://localhost:3001/api/export?includeInterpolated=false"

Advantages:

  • Smaller file size
  • Preserves annotation intent
  • Faster to export and import

Use when:

  • Sharing annotations with other analysts
  • Backing up annotation work
  • Transferring between systems

Fully Interpolated Mode

Exports all frames including interpolated ones.

curl "http://localhost:3001/api/export?includeInterpolated=true"

Advantages:

  • Frame-precise bounding boxes
  • No interpolation needed on import
  • Useful for training ML models

Use when:

  • Exporting for ML training
  • Need exact bounding boxes for every frame
  • Target system does not support interpolation

Example: Export All Annotations

curl "http://localhost:3001/api/export" --output annotations.jsonl

Example: Export for Specific Persona

curl "http://localhost:3001/api/export?personaIds=660e8400-e29b-41d4-a716-446655440001" \
--output persona-annotations.jsonl

Example: Export for Specific Video

curl "http://localhost:3001/api/export?videoIds=abc123def456" \
--output video-annotations.jsonl

Example: Export with Full Interpolation

curl "http://localhost:3001/api/export?includeInterpolated=true" \
--output annotations-full.jsonl

Example: Export as JSON Array

curl "http://localhost:3001/api/export?format=json" \
--output annotations.json

Export Statistics

Get export statistics without performing the export. Useful for estimating size before downloading.

Request

GET /api/export/stats

Query Parameters

ParameterTypeRequiredDescription
includeInterpolatedbooleanNoInclude interpolated frames in stats (default: false)
personaIdsstringNoComma-separated persona UUIDs to filter
videoIdsstringNoComma-separated video IDs to filter
annotationTypesstringNoComma-separated types to filter

Response

Status: 200 OK

{
"personaCount": 3,
"systemPersonaCount": 1,
"ontologyCount": 3,
"entityTypeCount": 8,
"eventTypeCount": 5,
"roleTypeCount": 4,
"relationTypeCount": 2,
"entityCount": 12,
"eventCount": 6,
"timeCount": 3,
"entityCollectionCount": 1,
"eventCollectionCount": 0,
"timeCollectionCount": 0,
"worldRelationCount": 4,
"summaryCount": 5,
"claimCount": 18,
"claimRelationCount": 7,
"annotationCount": 150,
"sequenceCount": 150,
"keyframeCount": 450,
"interpolatedFrameCount": 3600,
"totalSize": 104857600,
"totalSizeMB": "100.00MB",
"warning": "Large export. Consider filtering by persona or video."
}
FieldTypeDescription
personaCountnumberTotal number of personas
systemPersonaCountnumberNumber of system-generated personas included in personaCount
ontologyCountnumberNumber of persona ontologies
entityTypeCountnumberTotal entity types across all ontologies
eventTypeCountnumberTotal event types
roleTypeCountnumberTotal role types
relationTypeCountnumberTotal relation types
entityCountnumberWorld state entities
eventCountnumberWorld state events
timeCountnumberWorld state times
entityCollectionCountnumberEntity collections
eventCollectionCountnumberEvent collections
timeCollectionCountnumberTime collections
worldRelationCountnumberWorld state relations
summaryCountnumberVideo summaries
claimCountnumberClaims
claimRelationCountnumberClaim relations
annotationCountnumberAnnotations (filtered by persona/video/type if specified)
sequenceCountnumberBounding box sequences
keyframeCountnumberTotal keyframes
interpolatedFrameCountnumberTotal interpolated frames (0 if includeInterpolated is false)
totalSizenumberEstimated export size in bytes
totalSizeMBstringFormatted size in MB
warningstringOptional warning for large exports

Example

curl "http://localhost:3001/api/export/stats?includeInterpolated=true"

Export Personas

Export personas with their associated ontologies (type definitions).

Request

GET /api/export/personas

Response

Status: 200 OK

Content-Type: application/x-ndjson

JSON Lines format with personas followed by their ontologies:

{"type":"persona","data":{"id":"660e8400-e29b-41d4-a716-446655440001","name":"Analyst","role":"Video Analyst","informationNeed":"Track objects across frames","createdAt":"2025-10-06T14:30:00.000Z","updatedAt":"2025-10-06T14:30:00.000Z"}}
{"type":"ontology","data":{"personaId":"660e8400-e29b-41d4-a716-446655440001","entityTypes":[{"id":"entity-001","name":"Person","gloss":[{"type":"text","content":"A human being"}]}],"eventTypes":[],"roleTypes":[],"relationTypes":[]}}

Example

curl "http://localhost:3001/api/export/personas" --output personas.jsonl

Export World State

Export world state objects including entities, events, times, locations, collections, and relations.

Request

GET /api/export/world

Response

Status: 200 OK

Content-Type: application/x-ndjson

JSON Lines format with world state objects:

{"type":"entity","data":{"id":"entity-123","name":"John Smith","description":[{"type":"text","content":"A person in the video"}],"typeAssignments":[{"personaId":"660e8400","entityTypeId":"entity-001"}]}}
{"type":"event","data":{"id":"event-456","name":"Meeting","description":[{"type":"text","content":"A meeting event"}],"personaInterpretations":[]}}
{"type":"entity_collection","data":{"id":"coll-789","name":"Team Members","entityIds":["entity-123","entity-456"],"collectionType":"group"}}

Example

curl "http://localhost:3001/api/export/world" --output world-state.jsonl

Export Summaries

Export video summaries with their associated claims and claim relations.

Request

GET /api/export/summaries

Response

Status: 200 OK

Content-Type: application/x-ndjson

JSON Lines format with summaries followed by claims and claim relations:

{"type":"summary","data":{"id":"sum-123","videoId":"vid-456","personaId":"660e8400","summary":[{"type":"text","content":"Video summary content"}],"createdAt":"2025-10-06T14:30:00.000Z","updatedAt":"2025-10-06T14:30:00.000Z"}}
{"type":"claim","data":{"id":"claim-789","summaryId":"sum-123","summaryType":"video","text":"The person entered the room","gloss":[{"type":"text","content":"The person entered the room"}]}}
{"type":"claim_relation","data":{"id":"rel-012","sourceClaimId":"claim-789","targetClaimId":"claim-abc","relationTypeId":"supports"}}

Example

curl "http://localhost:3001/api/export/summaries" --output summaries.jsonl

Export All Data

Export all user-created data in dependency order: personas, ontologies, world state, summaries, claims, and annotations.

Request

GET /api/export/all

Response

Status: 200 OK

Content-Type: application/x-ndjson

JSON Lines format with all data types in dependency order:

{"type":"persona","data":{...}}
{"type":"ontology","data":{...}}
{"type":"entity","data":{...}}
{"type":"event","data":{...}}
{"type":"summary","data":{...}}
{"type":"claim","data":{...}}
{"type":"claim_relation","data":{...}}
{"type":"annotation","data":{...}}

Export Order

Data is exported in dependency order to ensure imports can be processed correctly:

  1. Personas - Must exist before ontologies
  2. Ontologies - Type definitions linked to personas
  3. World State - Entities, events, times, collections
  4. Summaries - Linked to videos and personas
  5. Claims - Linked to summaries
  6. Claim Relations - Linked to claims
  7. Annotations - Linked to videos and personas

Example

curl "http://localhost:3001/api/export/all" --output backup.jsonl

Import Data

Import all data types from a JSON Lines file with conflict resolution. The import system automatically processes data in dependency order.

Supported Import Types

  • persona - Personas with roles and information needs
  • ontology - Type definitions (entity, event, role, relation types)
  • entity - Entity world objects
  • event - Event world objects
  • time - Time references
  • entity_collection - Collections of entities
  • event_collection - Collections of events
  • time_collection - Collections of times
  • relation - Relations between world objects
  • summary - Video summaries
  • claim - Claims extracted from summaries
  • claim_relation - Relationships between claims
  • annotation - Bounding box annotations

Request

POST /api/import

Content-Type: multipart/form-data

Form Fields:

  • file: JSON Lines file (required)
  • options: Import options as JSON string (optional)

Import Options Schema

{
"conflictResolution": {
"personas": "skip",
"worldObjects": "skip",
"missingDependencies": "skip-item",
"duplicateIds": "preserve-id",
"sequences": {
"duplicateSequenceIds": "skip",
"overlappingFrameRanges": "fail-import",
"interpolationConflicts": "use-existing"
}
},
"scope": {
"includePersonas": true,
"includeWorldState": true,
"includeAnnotations": true
},
"validation": {
"strictMode": false,
"validateReferences": true,
"validateSequenceIntegrity": true
},
"transaction": {
"atomic": true
}
}
FieldTypeValuesDefaultDescription
conflictResolution.personasstringskip, replace, merge, renameskipHow to handle existing personas
conflictResolution.worldObjectsstringskip, replace, merge-assignmentsskipHow to handle existing world objects
conflictResolution.missingDependenciesstringskip-item, create-placeholder, fail-importskip-itemHow to handle missing dependencies
conflictResolution.duplicateIdsstringpreserve-id, regenerate-idpreserve-idHow to handle duplicate IDs
scope.includePersonasboolean-trueImport personas and ontologies
scope.includeWorldStateboolean-trueImport world state objects
scope.includeAnnotationsboolean-trueImport annotations
validation.strictModeboolean-falseReject items with warnings
validation.validateReferencesboolean-trueValidate all references exist
transaction.atomicboolean-trueAll-or-nothing import (rollback on error)

Response

Status: 200 OK

{
"success": true,
"summary": {
"totalLines": 250,
"processedLines": 250,
"importedItems": {
"personas": 5,
"ontologies": 5,
"entities": 20,
"events": 15,
"times": 10,
"entityCollections": 3,
"eventCollections": 2,
"timeCollections": 1,
"relations": 8,
"summaries": 12,
"claims": 45,
"claimRelations": 20,
"annotations": 100,
"totalKeyframes": 450,
"totalInterpolatedFrames": 3600,
"singleKeyframeSequences": 30
},
"skippedItems": {
"personas": 1,
"worldObjects": 3,
"summaries": 0,
"claims": 2,
"annotations": 5,
"sequenceAnnotations": 0
}
},
"warnings": [
{
"line": 42,
"type": "single_keyframe",
"message": "Annotation has only one keyframe"
},
{
"line": 78,
"type": "missing_reference",
"message": "Video xyz-123 not found, skipping annotation"
}
],
"errors": [],
"conflicts": [
{
"type": "duplicate-persona",
"line": 12,
"originalId": "persona-123",
"existingId": "persona-123",
"details": "Persona with same ID already exists",
"resolution": "skip"
}
]
}

Status: 400 Bad Request

{
"error": "Bad Request",
"message": "No file provided"
}

or

{
"error": "Parse Error",
"message": "Invalid JSON on line 42: Unexpected token"
}

Status: 500 Internal Server Error

{
"error": "Internal Server Error",
"message": "Database transaction failed"
}

Example: Import with Default Options

curl -X POST http://localhost:3001/api/import \
-F "file=@annotations.jsonl"

Example: Import with Custom Options

curl -X POST http://localhost:3001/api/import \
-F "file=@annotations.jsonl" \
-F 'options={"conflictResolution":{"duplicateIds":"overwrite"}}'

Example: Import with Strict Validation

curl -X POST http://localhost:3001/api/import \
-F "file=@annotations.jsonl" \
-F 'options={"validation":{"strictMode":true}}'

Preview Import

Preview import without committing to database. Performs parsing, validation, and conflict detection.

Request

POST /api/import/preview

Content-Type: multipart/form-data

Form Fields:

  • file: JSON Lines file (required)

Response

Status: 200 OK

{
"counts": {
"personas": 5,
"ontologies": 5,
"entities": 20,
"events": 15,
"times": 10,
"entityCollections": 3,
"eventCollections": 2,
"timeCollections": 1,
"relations": 8,
"summaries": 12,
"claims": 45,
"claimRelations": 20,
"annotations": 100,
"totalKeyframes": 450,
"singleKeyframeSequences": 30
},
"conflicts": [
{
"type": "duplicate-persona",
"line": 5,
"originalId": "persona-123",
"existingId": "persona-123",
"details": "Persona with same ID already exists"
},
{
"type": "duplicate-object",
"line": 42,
"originalId": "entity-456",
"existingId": "entity-456",
"details": "Entity with same ID already exists"
}
],
"warnings": [
"Line 42: Annotation has only one keyframe",
"Line 78: Missing persona reference for ontology"
]
}

Status: 400 Bad Request

{
"error": "Bad Request",
"message": "No file provided"
}

or

{
"error": "Parse Error",
"message": "Invalid JSON on line 42: Unexpected token"
}

Example

curl -X POST http://localhost:3001/api/import/preview \
-F "file=@backup.jsonl"

Import History

Retrieve history of import operations.

Request

GET /api/import/history

Query Parameters

ParameterTypeRequiredDescription
limitnumberNoMaximum records to return (1-100, default: 50)
offsetnumberNoNumber of records to skip (default: 0)

Response

Status: 200 OK

{
"imports": [
{
"id": "880e8400-e29b-41d4-a716-446655440003",
"filename": "annotations.jsonl",
"success": true,
"itemsImported": 145,
"itemsSkipped": 5,
"createdAt": "2025-10-06T14:30:00.000Z"
},
{
"id": "990e8400-e29b-41d4-a716-446655440004",
"filename": "external-annotations.jsonl",
"success": false,
"itemsImported": 0,
"itemsSkipped": 0,
"createdAt": "2025-10-05T10:15:00.000Z"
}
],
"total": 2
}

Status: 500 Internal Server Error

{
"error": "Internal Server Error",
"message": "Failed to retrieve import history"
}

Example

curl "http://localhost:3001/api/import/history?limit=10"

Notes

JSON Lines Format

Each line in a .jsonl file must be a valid JSON object representing a single annotation:

{"id":"...","videoId":"...","personaId":"...","annotationType":"type","typeAssignment":{"typeId":"...","typeName":"..."},"boundingBoxSequence":{...}}
{"id":"...","videoId":"...","personaId":"...","annotationType":"object","objectLink":{"objectId":"...","objectType":"entity"},"boundingBoxSequence":{...}}

File Size Limits

  • Maximum file size for import: 100 MB
  • Larger files should be split into multiple imports

Export Warning Threshold

Exports larger than 100 MB trigger a warning header suggesting filtering by persona or video.

Conflict Resolution Strategies

Duplicate IDs

  • skip: Do not import annotations with existing IDs
  • overwrite: Replace existing annotations with imported ones
  • merge: Attempt to merge sequences (add new keyframes)
  • fail: Abort import if duplicates found

Overlapping Frames

  • skip: Do not import annotations with overlapping frame ranges
  • merge: Combine sequences (may create complex merged sequences)
  • overwrite: Replace existing frames with imported ones
  • fail: Abort import if overlaps found

Missing Dependencies

  • skip: Do not import annotations with missing personas/videos
  • create: Create placeholder personas/videos (not recommended)
  • fail: Abort import if dependencies missing

Import Transaction Modes

Atomic Mode (default)

All annotations are imported in a single database transaction. If any annotation fails, the entire import is rolled back.

Advantages:

  • Database consistency
  • All-or-nothing guarantee

Use when:

  • Data integrity is critical
  • Small to medium imports

Non-Atomic Mode

Each annotation is imported individually. Failed annotations are logged but do not affect others.

{
"transaction": {
"atomic": false
}
}

Advantages:

  • Partial imports succeed
  • Better for large files with errors

Use when:

  • Importing from external sources with quality issues
  • Large imports where some failures are acceptable