Project Data Import
The project data import API creates a new project's data graph from a knora-api (v2 external schema) JSON-LD payload. The server transforms the payload into the internal knora-base representation, validates it, and streams it into the triplestore.
Unlike the Project Migration Export/Import — which moves a complete project (admin data, ontologies, permissions, assets) between instances as a BagIt package — the data import handles instance data only. The project and its ontologies must already exist on the instance, and the project's data graph must not exist yet (create-only).
Endpoints
For request/response schemas, error codes, and interactive testing, see the OpenAPI documentation.
| Route | Method | Description |
|---|---|---|
/v3/projects/{projectIri}/data-imports |
POST |
Upload JSON-LD and trigger async import |
/v3/projects/{projectIri}/data-imports/{importId} |
GET |
Poll import status |
/v3/projects/{projectIri}/data-imports/{importId} |
DELETE |
Delete a completed/failed import |
Authentication and Authorization
All endpoints require a valid Bearer JWT token and SystemAdmin permissions.
Requests from non-SystemAdmin users (e.g. project admins) are rejected with 403 Forbidden.
Feature Flag
The endpoints are gated behind the
allow-project-data-import feature flag,
which is disabled by default. When disabled, the endpoints return 404 Not Found.
Request Format
The request body is the project's data graph as JSON-LD in the knora-api v2 external (complex) schema, with content
type application/ld+json. The payload contains resources and their values only — no admin data, ontologies, or
permission data.
Resource and value metadata that is managed by the server is synthesised during the import and need not (and should not) be supplied in the payload:
attachedToProjectis derived from the{projectIri}path parameter.attachedToUseris the authenticated user.hasPermissionsis resolved once from the project's default object access permissions (DOAPs) as they apply to the authenticated user, and applied uniformly to every resource and value. Since the importer is always a system admin, the project's ProjectAdmin-group DOAP has first precedence. Per-resource-class and per-property DOAPs are not resolved per entity.- Creation dates are set to the time of the import.
@graph declarations in the payload are ignored: all data is written exclusively into the project's data named
graph, which is derived from the project.
Key Behaviors
The import is asynchronous. Triggering an import returns 202 Accepted with a task ID.
Poll the status endpoint until status is completed or failed.
The status field is one of: in_progress, completed, failed.
The import is create-only: if the project already has a data graph, the request is rejected with
409 Conflict and error code data_graph_exists. The precondition is checked synchronously when the import is
triggered and re-verified immediately before the upload. Updating or extending an existing data graph is not
possible with this API.
Only one data-graph import can exist at a time. Attempting to create a second returns 409 Conflict with the
existing task's id in the error details. Delete the previous task before triggering a new one. Data-graph imports
are tracked independently of migration imports and exports.
The upload to Fuseki is atomic — if the upload fails, no partial data is written to the triplestore.
Import Validation
Before anything is written to the triplestore, the transformed data is SHACL-validated against the same data shapes used by the migration import. The project's ontologies are fetched from the triplestore to support the validation. Validation failure fails the task with a descriptive error message and leaves the triplestore untouched.
Typical Workflow
# Upload and trigger import
curl -s --request POST \
--url 'https://server/v3/projects/http%3A%2F%2Frdfh.ch%2Fprojects%2F0001/data-imports' \
--header 'Authorization: Bearer <jwt>' \
--header 'Content-Type: application/ld+json' \
--data-binary @project-data.jsonld
# Response: {"id": "<importId>", "status": "in_progress", ...}
# Poll status until completed
curl -s --request GET \
--url 'https://server/v3/projects/http%3A%2F%2Frdfh.ch%2Fprojects%2F0001/data-imports/<importId>' \
--header 'Authorization: Bearer <jwt>'
# Response: {"status": "completed", ...}
# Cleanup
curl --request DELETE \
--url 'https://server/v3/projects/http%3A%2F%2Frdfh.ch%2Fprojects%2F0001/data-imports/<importId>' \
--header 'Authorization: Bearer <jwt>'
Limitations
- Project and ontologies must already exist: The import assumes class and property IRIs in the payload resolve against ontologies already in the triplestore.
- Create-only: Re-importing requires deleting the project's data graph first, which is out of scope for this API.
- No assets: Binary assets are not part of the import; only RDF data is handled.
- JSON-LD only: Other RDF serializations are not accepted.
- Single instance: Task state is held in memory per instance (same constraint as migration import/export).