Getting Started
Quick start guide for the sovity EDC API Wrapper
Getting Started
This guide will help you make your first API call to the sovity EDC API Wrapper. The UI API provides a simplified, type-safe interface for managing your EDC Connector.
Prerequisites
Before you begin, ensure you have:
- Access to an EDC Connector instance (provided by your Datenraum Kultur administrator)
- An API key for authentication
- A tool for making HTTP requests (curl, Postman, or your preferred HTTP client)
Base URL
All API requests should be made to your connector instance's Management API:
https://api.your-connector-instance.prod.truzztbox.eu/api/managementReplace this with your actual connector URL.
API Structure
The sovity UI API uses a page-based structure that provides all data needed for specific UI views:
| Endpoint | Purpose |
|---|---|
/wrapper/ui/pages/dashboard-page | Connector overview and statistics |
/wrapper/ui/pages/asset-page | Asset management |
/wrapper/ui/pages/policy-page | Policy definitions |
/wrapper/ui/pages/contract-definition-page | Contract definitions |
/wrapper/ui/pages/contract-agreement-page | Contract agreements |
/wrapper/ui/pages/catalog-page/data-offers | Catalog browsing |
/wrapper/ui/pages/transfer-history-page | Transfer history |
/wrapper/ui/pages/create-data-offer | Quick data offer creation |
Your First API Call: Dashboard
Let's start by querying the Dashboard to get an overview of your connector:
curl -X GET "https://api.your-connector-instance.prod.truzztbox.eu/api/management/wrapper/ui/pages/dashboard-page" \
-H "Content-Type: application/json" \
-H "X-Api-Key: your-api-key"const BASE_URL = 'https://api.your-connector-instance.prod.truzztbox.eu/api/management';
const response = await fetch(`${BASE_URL}/wrapper/ui/pages/dashboard-page`, {
headers: {
'Content-Type': 'application/json',
'X-Api-Key': 'your-api-key',
},
});
const dashboard = await response.json();
console.log('Connector:', dashboard.connectorTitle);
console.log('Assets:', dashboard.numAssets);
console.log('Policies:', dashboard.numPolicies);
console.log('Contract Definitions:', dashboard.numContractDefinitions);Dashboard Response
{
"numAssets": 5,
"numPolicies": 3,
"numContractDefinitions": 4,
"numContractAgreementsConsuming": 2,
"numContractAgreementsProviding": 7,
"transferProcessesConsuming": {
"numTotal": 10,
"numRunning": 1,
"numOk": 8,
"numError": 1
},
"transferProcessesProviding": {
"numTotal": 15,
"numRunning": 0,
"numOk": 14,
"numError": 1
},
"connectorEndpoint": "https://your-connector.truzztbox.eu/protocol",
"connectorParticipantId": "BPNL000000000001",
"connectorTitle": "Datenraum Kultur Connector",
"connectorDescription": "EDC Connector for cultural data exchange",
"connectorCuratorName": "Your Organization",
"connectorCuratorUrl": "https://your-organization.de",
"managementApiUrlShownInDashboard": "https://api.your-connector-instance.prod.truzztbox.eu/api/management"
}Quick Data Offer Creation
The fastest way to publish data is using the Quick Data Offer endpoint. This creates an asset, policy, and contract definition in one call.
This endpoint uses a flat structure where all asset fields are at the root level, not nested inside an asset object.
curl -X POST "https://api.your-connector-instance.prod.truzztbox.eu/api/management/wrapper/ui/pages/create-data-offer" \
-H "Content-Type: application/json" \
-H "X-Api-Key: your-api-key" \
-d '{
"id": "museum-collection-2024",
"title": "Museum Collection Metadata 2024",
"description": "Comprehensive metadata for our 2024 digital collection",
"language": "https://w3id.org/idsa/code/DE",
"version": "1.0",
"keywords": ["museum", "cultural-heritage", "metadata"],
"mediaType": "application/json",
"publisherHomepage": "",
"licenseUrl": "",
"landingPageUrl": "",
"drkAssetType": "MUSEUM",
"drkMuseumName": "Hamburger Kunsthalle",
"dataSource": {
"type": "HTTP_DATA",
"httpData": {
"method": "GET",
"baseUrl": "https://api.museum.example.com/collection/2024",
"queryString": "",
"authHeaderValue": {},
"headers": {},
"enableMethodParameterization": false,
"enablePathParameterization": false,
"enableQueryParameterization": false,
"enableBodyParameterization": false
}
},
"publishType": "PUBLISH_UNRESTRICTED"
}'type DrkAssetType = 'GENERAL' | 'MUSEUM' | 'THEATRE_PLAN' | 'MUSICSCHOOL';
interface DataOfferCreateRequest {
// Required
id: string;
dataSource: {
type: 'HTTP_DATA' | 'ON_REQUEST' | 'CUSTOM';
httpData?: {
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
baseUrl: string;
queryString?: string;
authHeaderValue?: Record<string, string>;
headers?: Record<string, string>;
enableMethodParameterization?: boolean;
enablePathParameterization?: boolean;
enableQueryParameterization?: boolean;
enableBodyParameterization?: boolean;
};
onRequest?: {
contactEmail: string;
contactPreferredEmailSubject: string;
};
};
// Optional metadata
title?: string;
description?: string;
language?: string; // IDS URI, e.g., "https://w3id.org/idsa/code/DE"
version?: string;
keywords?: string[];
mediaType?: string;
publisherHomepage?: string;
licenseUrl?: string;
landingPageUrl?: string; // Link to asset documentation
// DRK-specific (all optional, default drkAssetType = 'GENERAL')
drkAssetType?: DrkAssetType;
drkMuseumName?: string | null; // When drkAssetType = 'MUSEUM'
drkTheatreName?: string | null; // When drkAssetType = 'THEATRE_PLAN'
drkTheatreStreetaddress?: string | null;
drkTheatrePostalCode?: string | null;
drkTheatreLocality?: string | null;
drkTheatreCountry?: string | null;
drkMusicSchoolName?: string | null; // When drkAssetType = 'MUSICSCHOOL'
// Policy (optional)
publishType?: 'DONT_PUBLISH' | 'PUBLISH_UNRESTRICTED' | 'PUBLISH_RESTRICTED';
policyExpression?: UiPolicyExpression;
}
const request: DataOfferCreateRequest = {
id: 'museum-collection-2024',
title: 'Museum Collection Metadata 2024',
description: 'Comprehensive metadata for our 2024 digital collection',
language: 'https://w3id.org/idsa/code/DE',
version: '1.0',
keywords: ['museum', 'cultural-heritage', 'metadata'],
mediaType: 'application/json',
landingPageUrl: 'https://museum.example.com/api-docs',
drkAssetType: 'MUSEUM',
drkMuseumName: 'Hamburger Kunsthalle',
dataSource: {
type: 'HTTP_DATA',
httpData: {
method: 'GET',
baseUrl: 'https://api.museum.example.com/collection/2024',
},
},
publishType: 'PUBLISH_UNRESTRICTED',
};
const response = await fetch(
`${BASE_URL}/wrapper/ui/pages/create-data-offer`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': 'your-api-key',
},
body: JSON.stringify(request),
}
);
const result = await response.json();
console.log('Created data offer with ID:', result.id);Publish Types
| Type | Description |
|---|---|
DONT_PUBLISH | Create asset only, no contract definition |
PUBLISH_UNRESTRICTED | Create with always-true policy (anyone can access) |
PUBLISH_RESTRICTED | Create with custom policy expression |
All publish types are optional. If not specified, only the asset is created.
DRK Asset Types
Assets can be categorized by cultural domain using drkAssetType:
| Asset Type | Description | Conditional Fields |
|---|---|---|
GENERAL (default) | General purpose data asset | None |
MUSEUM | Museum-related data | drkMuseumName |
THEATRE_PLAN | Theatre schedule data | drkTheatreName, drkTheatreStreetaddress, drkTheatrePostalCode, drkTheatreLocality, drkTheatreCountry |
MUSICSCHOOL | Music school data | drkMusicSchoolName |
Theatre Example
const theatreOffer: DataOfferCreateRequest = {
id: 'theatre-schedule-2024',
title: 'Theatre Performance Schedule 2024',
description: 'Machine-readable theatre schedule data',
language: 'https://w3id.org/idsa/code/DE',
version: '1.0',
keywords: ['theatre', 'schedule', 'performances'],
mediaType: 'application/json',
drkAssetType: 'THEATRE_PLAN',
drkTheatreName: 'Deutsches Schauspielhaus',
drkTheatreStreetaddress: 'Kirchenallee 39',
drkTheatrePostalCode: '20099',
drkTheatreLocality: 'Hamburg',
drkTheatreCountry: 'Germany',
dataSource: {
type: 'HTTP_DATA',
httpData: {
method: 'GET',
baseUrl: 'https://api.theatre.example.com/schedule',
},
},
publishType: 'PUBLISH_UNRESTRICTED',
};Restricted Publishing Example
const restrictedOffer: DataOfferCreateRequest = {
id: 'research-dataset-2024',
title: 'Research Dataset 2024',
language: 'https://w3id.org/idsa/code/EN',
drkAssetType: 'GENERAL',
dataSource: {
type: 'HTTP_DATA',
httpData: {
method: 'GET',
baseUrl: 'https://api.research.example.com/dataset',
},
},
publishType: 'PUBLISH_RESTRICTED',
policyExpression: {
type: 'AND',
expressions: [
{
type: 'CONSTRAINT',
constraint: {
left: 'purpose',
operator: 'EQ',
right: { type: 'STRING', value: 'research' },
},
},
{
type: 'CONSTRAINT',
constraint: {
left: 'participantType',
operator: 'IN',
right: {
type: 'STRING_LIST',
valueList: ['university', 'research-institute'],
},
},
},
],
},
};List Your Assets
Retrieve all assets in your connector:
curl -X GET "https://api.your-connector-instance.prod.truzztbox.eu/api/management/wrapper/ui/pages/asset-page" \
-H "Content-Type: application/json" \
-H "X-Api-Key: your-api-key"interface UiAsset {
assetId: string;
title: string;
description?: string;
dataSourceAvailability: 'LIVE' | 'ON_REQUEST';
creatorOrganizationName: string;
keywords?: string[];
// ... more fields
}
interface AssetPage {
assets: UiAsset[];
}
const response = await fetch(`${BASE_URL}/wrapper/ui/pages/asset-page`, {
headers: {
'Content-Type': 'application/json',
'X-Api-Key': 'your-api-key',
},
});
const page: AssetPage = await response.json();
console.log('Total assets:', page.assets.length);
page.assets.forEach((asset) => {
console.log(`- ${asset.assetId}: ${asset.title}`);
});Browse a Catalog
Discover data offers from other connectors:
curl -X GET "https://api.your-connector-instance.prod.truzztbox.eu/api/management/wrapper/ui/pages/catalog-page/data-offers?connectorEndpoint=https://other-connector.truzztbox.eu/protocol" \
-H "Content-Type: application/json" \
-H "X-Api-Key: your-api-key"interface UiDataOffer {
endpoint: string;
participantId: string;
asset: UiAsset;
contractOffers: Array<{
contractOfferId: string;
policy: UiPolicy;
}>;
}
async function browseCatalog(connectorEndpoint: string): Promise<UiDataOffer[]> {
const params = new URLSearchParams({ connectorEndpoint });
const response = await fetch(
`${BASE_URL}/wrapper/ui/pages/catalog-page/data-offers?${params}`,
{
headers: {
'Content-Type': 'application/json',
'X-Api-Key': 'your-api-key',
},
}
);
if (!response.ok) {
throw new Error(`Failed to fetch catalog: ${response.statusText}`);
}
return response.json();
}
const offers = await browseCatalog('https://other-connector.truzztbox.eu/protocol');
console.log('Available data offers:', offers.length);
offers.forEach((offer) => {
console.log(`- ${offer.asset.title} (${offer.contractOffers.length} contract offers)`);
});Complete Workflow Example
Check Connector Status
Verify your connector is operational:
const dashboard = await fetch(`${BASE_URL}/wrapper/ui/pages/dashboard-page`, {
headers: { 'Content-Type': 'application/json', 'X-Api-Key': 'your-api-key' },
}).then((r) => r.json());
console.log('Connector:', dashboard.connectorTitle);
console.log('Participant ID:', dashboard.connectorParticipantId);Create a Data Offer
Publish your first dataset:
const offer = await fetch(`${BASE_URL}/wrapper/ui/pages/create-data-offer`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-Api-Key': 'your-api-key' },
body: JSON.stringify({
id: 'my-first-dataset',
title: 'My First Dataset',
language: 'https://w3id.org/idsa/code/DE',
drkAssetType: 'GENERAL',
dataSource: {
type: 'HTTP_DATA',
httpData: {
method: 'GET',
baseUrl: 'https://my-api.example.com/data'
},
},
publishType: 'PUBLISH_UNRESTRICTED',
}),
}).then((r) => r.json());
console.log('Created:', offer.id);Verify in Asset Page
Confirm the asset was created:
const assets = await fetch(`${BASE_URL}/wrapper/ui/pages/asset-page`, {
headers: { 'Content-Type': 'application/json', 'X-Api-Key': 'your-api-key' },
}).then((r) => r.json());
const myAsset = assets.assets.find((a) => a.assetId === 'my-first-dataset');
console.log('Asset found:', myAsset?.title);Browse Other Catalogs
Discover data from partner connectors:
const partnerOffers = await fetch(
`${BASE_URL}/wrapper/ui/pages/catalog-page/data-offers?connectorEndpoint=https://partner.truzztbox.eu/protocol`,
{
headers: { 'Content-Type': 'application/json', 'X-Api-Key': 'your-api-key' },
}
).then((r) => r.json());
console.log('Partner offers:', partnerOffers.length);Key Differences from Standard EDC API
The sovity UI API differs from the standard Eclipse EDC Management API:
| Feature | Standard EDC API | sovity UI API |
|---|---|---|
| Format | JSON-LD with @context | Plain JSON |
| Endpoints | /v3/assets, /v3/policydefinitions | /wrapper/ui/pages/... |
| Query | QuerySpec with filterExpression | Page-based, pre-aggregated |
| Data Offers | Separate asset + policy + contract definition | Single create-data-offer endpoint |
| States | Raw EDC state codes | Simplified states (RUNNING, OK, ERROR) |
The sovity UI API wraps the standard EDC API to provide a simpler, more type-safe interface. All operations are still EDC-compliant.