EDC Connector API
Concepts

Assets

Understanding Assets in the sovity EDC Connector

Assets

An Asset is a fundamental concept in the EDC representing a digital resource that can be shared through the data space. Assets contain metadata describing the resource and a Data Source specifying where and how to access the actual data.

Asset Structure

The sovity EDC API uses a type-safe UiAsset structure that simplifies asset management compared to the raw EDC JSON-LD format.

Core Fields

FieldRequiredDescription
idYesUnique identifier for the asset
dataSourceYesConfiguration for accessing the actual data
titleNoHuman-readable title
descriptionNoDetailed description (supports Markdown)
versionNoVersion identifier
languageNoLanguage code as IDS URI (see Language Codes)
keywordsNoArray of keywords for discoverability
mediaTypeNoMIME type of the data

Metadata Fields

FieldDescription
publisherHomepageURL to the publisher's website
licenseUrlURL to the license terms
landingPageUrlURL to external documentation or landing page for the asset
dataCategoryCategory classification
dataSubcategorySubcategory classification
dataModelData model or schema identifier
sovereignLegalNameLegal owner of the data (if different from publisher)

Geographic and Temporal Fields

FieldDescription
geoLocationGeographic location description
geoReferenceMethodMethod used for geo-referencing
nutsLocationsNUTS region codes (EU administrative divisions)
temporalCoverageFromStart date of data coverage
temporalCoverageToInclusiveEnd date of data coverage (inclusive)
transportModeTransport mode (for mobility data)

Custom Properties

FieldDescription
customJsonAsStringCustom properties as JSON string
customJsonLdAsStringCustom properties as JSON-LD string
privateCustomJsonAsStringPrivate custom properties (not visible to consumers)
privateCustomJsonLdAsStringPrivate custom properties as JSON-LD

DRK-Specific Fields (Datenraum Kultur)

These fields are specific to the Datenraum Kultur (Cultural Data Space) and help categorize assets by cultural domain.

DRK Asset Type

The drkAssetType field categorizes the asset by its cultural domain. If not specified, it defaults to GENERAL.

Asset TypeDescriptionConditional Fields
GENERALGeneral purpose data asset (default)None
MUSEUMMuseum-related data (collections, artworks, metadata)drkMuseumName
THEATRE_PLANTheatre schedule and performance datadrkTheatreName, drkTheatreStreetaddress, drkTheatrePostalCode, drkTheatreLocality, drkTheatreCountry
MUSICSCHOOLMusic school and education datadrkMusicSchoolName

Conditional DRK Fields

Depending on the drkAssetType, you can provide additional metadata:

For MUSEUM assets:

FieldDescription
drkMuseumNameName of the museum providing the data

For THEATRE_PLAN assets:

FieldDescription
drkTheatreNameName of the theatre
drkTheatreStreetaddressStreet address of the theatre
drkTheatrePostalCodePostal code
drkTheatreLocalityCity or locality
drkTheatreCountryCountry

For MUSICSCHOOL assets:

FieldDescription
drkMusicSchoolNameName of the music school

Language Codes

The language field uses IDS (International Data Spaces) language code URIs. Common codes include:

LanguageIDS URI
Germanhttps://w3id.org/idsa/code/DE
Englishhttps://w3id.org/idsa/code/EN

For a complete list of language codes, see the IDS Information Model Language Codes.

Data Source Types

The dataSource field defines how the actual data is accessed. Three types are supported:

HTTP_DATA

For assets served via HTTP/HTTPS endpoints:

const httpDataSource = {
  type: 'HTTP_DATA',
  httpData: {
    baseUrl: 'https://api.example.com/data/v1',
    method: 'GET', // GET, POST, PUT, PATCH, DELETE, OPTIONS
    
    // Optional: Query parameters
    queryString: 'format=json&limit=100',
    
    // Optional: Authentication
    authHeaderName: 'Authorization',
    authHeaderValue: {
      secretName: 'my-api-key', // Reference to vault secret
      // OR
      rawValue: 'Bearer token123' // Inline value (less secure)
    },
    
    // Optional: Additional headers
    headers: {
      'Accept': 'application/json',
      'X-Custom-Header': 'value'
    },
    
    // Optional: Parameterization (allows consumer to customize requests)
    enableMethodParameterization: false,
    enablePathParameterization: true,
    enableQueryParameterization: true,
    enableBodyParameterization: false
  }
};

Parameterization Options

OptionDescription
enableMethodParameterizationConsumer can specify HTTP method
enablePathParameterizationConsumer can append to the path
enableQueryParameterizationConsumer can add query parameters
enableBodyParameterizationConsumer can provide request body (POST/PUT/PATCH only)

ON_REQUEST

For assets that require manual data provision (no automated data source):

const onRequestDataSource = {
  type: 'ON_REQUEST',
  onRequest: {
    contactEmail: 'data-requests@museum.example.com',
    contactPreferredEmailSubject: 'Data Request: Museum Collection API Access'
  }
};

Use this when:

  • Data requires manual approval or preparation
  • Data is provided through offline channels
  • You want to collect interest before setting up automated access

CUSTOM

For custom data address types not covered by HTTP_DATA or ON_REQUEST:

const customDataSource = {
  type: 'CUSTOM',
  customProperties: {
    'type': 'AmazonS3',
    'bucketName': 'my-data-bucket',
    'region': 'eu-central-1',
    'objectName': 'datasets/collection.json'
  }
};

Creating an Asset

Using the Asset Endpoint

Endpoint: POST /wrapper/ui/pages/asset-page/assets

cURL Example

curl -X POST "https://api.your-connector-instance.prod.truzztbox.eu/api/management/wrapper/ui/pages/asset-page/assets" \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: your-api-key" \
  -d '{
    "id": "museum-collection-2024",
    "title": "Museum Digital Collection",
    "description": "Digitized artworks from the museum collection including metadata and high-resolution images.",
    "version": "1.0",
    "language": "en",
    "keywords": ["museum", "art", "digital", "collection"],
    "mediaType": "application/json",
    "dataCategory": "Cultural Heritage",
    "dataSubcategory": "Museum Collections",
    "licenseUrl": "https://creativecommons.org/licenses/by/4.0/",
    "dataSource": {
      "type": "HTTP_DATA",
      "httpData": {
        "baseUrl": "https://api.museum.example.com/collection/v1",
        "method": "GET",
        "authHeaderName": "X-API-Key",
        "authHeaderValue": {
          "secretName": "museum-api-key"
        },
        "enablePathParameterization": true,
        "enableQueryParameterization": true
      }
    }
  }'

TypeScript Example

interface UiAssetCreateRequest {
  id: string;
  title?: string;
  description?: string;
  version?: string;
  language?: string;
  keywords?: string[];
  mediaType?: string;
  dataCategory?: string;
  dataSubcategory?: string;
  licenseUrl?: string;
  publisherHomepage?: string;
  landingPageUrl?: string;
  dataSource: {
    type: 'HTTP_DATA' | 'ON_REQUEST' | 'CUSTOM';
    httpData?: {
      baseUrl: string;
      method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS';
      queryString?: string;
      authHeaderName?: string;
      authHeaderValue?: { secretName?: string; rawValue?: string };
      headers?: Record<string, string>;
      enableMethodParameterization?: boolean;
      enablePathParameterization?: boolean;
      enableQueryParameterization?: boolean;
      enableBodyParameterization?: boolean;
    };
    onRequest?: {
      contactEmail: string;
      contactPreferredEmailSubject: string;
    };
    customProperties?: Record<string, string>;
  };
}

const asset: UiAssetCreateRequest = {
  id: 'museum-collection-2024',
  title: 'Museum Digital Collection',
  description: 'Digitized artworks from the museum collection.',
  version: '1.0',
  language: 'en',
  keywords: ['museum', 'art', 'digital', 'collection'],
  mediaType: 'application/json',
  dataCategory: 'Cultural Heritage',
  dataSource: {
    type: 'HTTP_DATA',
    httpData: {
      baseUrl: 'https://api.museum.example.com/collection/v1',
      method: 'GET',
      authHeaderName: 'X-API-Key',
      authHeaderValue: { secretName: 'museum-api-key' },
      enablePathParameterization: true,
      enableQueryParameterization: true,
    },
  },
};

const response = await fetch(
  'https://api.your-connector-instance.prod.truzztbox.eu/api/management/wrapper/ui/pages/asset-page/assets',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Api-Key': 'your-api-key',
    },
    body: JSON.stringify(asset),
  }
);

const result = await response.json();
console.log('Created asset:', result.id);

Response

{
  "id": "museum-collection-2024",
  "lastUpdatedDate": "2024-01-15T10:30:00Z"
}

Quick Data Offer Creation

For a streamlined workflow, use the Create Data Offer endpoint to create an asset, policy, and contract definition in a single call.

Endpoint: POST /wrapper/ui/pages/create-data-offer

This endpoint uses a flat structure where all asset fields are at the root level, not nested inside an asset object.

Publish Types

TypeDescription
DONT_PUBLISHOnly create the asset, no policy or contract definition
PUBLISH_UNRESTRICTEDCreate asset with an always-true policy (public access)
PUBLISH_RESTRICTEDCreate asset with a custom policy expression

All publish types are optional. If not specified, only the asset is created.

cURL Example (Museum Asset)

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 Digital Collection 2024",
    "description": "Digitized artworks from our permanent collection",
    "language": "https://w3id.org/idsa/code/DE",
    "version": "1.0",
    "keywords": ["museum", "art", "digital-collection"],
    "mediaType": "application/json",
    "publisherHomepage": "https://museum.example.com",
    "licenseUrl": "https://creativecommons.org/licenses/by/4.0/",
    "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",
        "queryString": "",
        "authHeaderValue": {},
        "headers": {},
        "enableMethodParameterization": false,
        "enablePathParameterization": false,
        "enableQueryParameterization": false,
        "enableBodyParameterization": false
      }
    },
    "publishType": "PUBLISH_UNRESTRICTED"
  }'

TypeScript Example (Theatre Asset)

type DrkAssetType = 'GENERAL' | 'MUSEUM' | 'THEATRE_PLAN' | 'MUSICSCHOOL';

interface DataOfferCreateRequest {
  // Required
  id: string;
  dataSource: UiDataSource;
  
  // Optional metadata
  title?: string;
  description?: string;
  language?: string;                    // IDS URI
  version?: string;
  keywords?: string[];
  mediaType?: string;
  publisherHomepage?: string;
  licenseUrl?: string;
  landingPageUrl?: string;
  
  // DRK-specific (all optional, default drkAssetType = 'GENERAL')
  drkAssetType?: DrkAssetType;
  drkMuseumName?: string | null;
  drkTheatreName?: string | null;
  drkTheatreStreetaddress?: string | null;
  drkTheatrePostalCode?: string | null;
  drkTheatreLocality?: string | null;
  drkTheatreCountry?: string | null;
  drkMusicSchoolName?: string | null;
  
  // Policy (optional)
  publishType?: 'DONT_PUBLISH' | 'PUBLISH_UNRESTRICTED' | 'PUBLISH_RESTRICTED';
  policyExpression?: UiPolicyExpression;
}

const theatreDataOffer: 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',
  landingPageUrl: 'https://theatre.example.com/api-docs',
  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',
      enableQueryParameterization: true,
    },
  },
  publishType: 'PUBLISH_UNRESTRICTED',
};

const response = await fetch(
  'https://api.your-connector-instance.prod.truzztbox.eu/api/management/wrapper/ui/pages/create-data-offer',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Api-Key': 'your-api-key',
    },
    body: JSON.stringify(theatreDataOffer),
  }
);

const result = await response.json();
console.log('Created data offer:', result.id);

Music School Example

const musicSchoolDataOffer: DataOfferCreateRequest = {
  id: 'music-lessons-catalog-2024',
  title: 'Music Lessons Catalog',
  description: 'Available music lessons and instructors',
  language: 'https://w3id.org/idsa/code/DE',
  version: '1.0',
  keywords: ['music', 'education', 'lessons'],
  mediaType: 'application/json',
  drkAssetType: 'MUSICSCHOOL',
  drkMusicSchoolName: 'Hamburger Konservatorium',
  dataSource: {
    type: 'HTTP_DATA',
    httpData: {
      method: 'GET',
      baseUrl: 'https://api.musicschool.example.com/catalog',
    },
  },
  publishType: 'PUBLISH_RESTRICTED',
  policyExpression: {
    type: 'CONSTRAINT',
    constraint: {
      left: 'purpose',
      operator: 'EQ',
      right: { type: 'STRING', value: 'education' },
    },
  },
};

Listing Assets

Endpoint: GET /wrapper/ui/pages/asset-page

cURL Example

curl -X GET "https://api.your-connector-instance.prod.truzztbox.eu/api/management/wrapper/ui/pages/asset-page" \
  -H "X-Api-Key: your-api-key"

TypeScript Example

interface AssetPage {
  assets: UiAsset[];
}

interface UiAsset {
  assetId: string;
  title: string;
  description?: string;
  dataSourceAvailability: 'LIVE' | 'ON_REQUEST';
  creatorOrganizationName: string;
  isOwnConnector: boolean;
  // ... additional fields
}

const response = await fetch(
  'https://api.your-connector-instance.prod.truzztbox.eu/api/management/wrapper/ui/pages/asset-page',
  {
    headers: { 'X-Api-Key': 'your-api-key' },
  }
);

const assetPage: AssetPage = await response.json();
console.log(`Found ${assetPage.assets.length} assets`);

// Filter your own assets
const myAssets = assetPage.assets.filter(a => a.isOwnConnector);

Editing an Asset

Endpoint: PUT /wrapper/ui/pages/asset-page/assets/{assetId}

cURL Example

curl -X PUT "https://api.your-connector-instance.prod.truzztbox.eu/api/management/wrapper/ui/pages/asset-page/assets/museum-collection-2024" \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: your-api-key" \
  -d '{
    "title": "Museum Digital Collection - Updated",
    "description": "Updated description with new information",
    "version": "1.1",
    "keywords": ["museum", "art", "digital", "collection", "updated"]
  }'

TypeScript Example

interface UiAssetEditRequest {
  title?: string;
  description?: string;
  version?: string;
  keywords?: string[];
  // ... other editable fields
  dataSourceOverrideOrNull?: UiDataSource; // Optional: update data source
}

const update: UiAssetEditRequest = {
  title: 'Museum Digital Collection - Updated',
  description: 'Updated description with new information',
  version: '1.1',
};

await fetch(
  'https://api.your-connector-instance.prod.truzztbox.eu/api/management/wrapper/ui/pages/asset-page/assets/museum-collection-2024',
  {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
      'X-Api-Key': 'your-api-key',
    },
    body: JSON.stringify(update),
  }
);

Deleting an Asset

Endpoint: DELETE /wrapper/ui/pages/asset-page/assets/{assetId}

cURL Example

curl -X DELETE "https://api.your-connector-instance.prod.truzztbox.eu/api/management/wrapper/ui/pages/asset-page/assets/museum-collection-2024" \
  -H "X-Api-Key: your-api-key"

Assets referenced by active Contract Agreements cannot be deleted. You must terminate or wait for all related agreements to expire first.

Validating Asset IDs

Before creating an asset, you can check if an ID is already taken:

Endpoint: GET /wrapper/ui/pages/data-offer-page/validate-asset-id/{assetId}

interface IdAvailabilityResponse {
  id: string;
  available: boolean;
}

const response = await fetch(
  'https://api.your-connector-instance.prod.truzztbox.eu/api/management/wrapper/ui/pages/data-offer-page/validate-asset-id/my-new-asset',
  { headers: { 'X-Api-Key': 'your-api-key' } }
);

const result: IdAvailabilityResponse = await response.json();
if (result.available) {
  console.log('ID is available, proceed with creation');
} else {
  console.log('ID already taken, choose a different one');
}

Asset Lifecycle

  1. Create: Define the asset with metadata and data source
  2. Validate: Optionally check ID availability before creation
  3. Link: Create a Contract Definition to make the asset discoverable
  4. Discover: Asset appears in the federated catalog for consumers
  5. Negotiate: Consumers negotiate for access through contract offers
  6. Transfer: Data is transferred under the agreed policy terms
  7. Update: Modify asset metadata as needed
  8. Delete: Remove when no longer needed

Best Practices

  1. Use meaningful IDs: Choose descriptive, URL-safe identifiers
  2. Complete metadata: Provide comprehensive descriptions for discoverability
  3. Use vault secrets: Store authentication credentials securely using secretName instead of rawValue
  4. Enable appropriate parameterization: Only enable the parameterization options consumers actually need
  5. Version your assets: Use semantic versioning in the version field
  6. Add keywords: Help consumers find your assets through search

Next Steps

On this page