{
  "manifest_version": "1.0.0",
  "semantic_id": "dk_datafordeler_graphql_platform_v1",
  "data_status": "SOURCE",
  "intent": {
    "scientific_purpose": "Define the shared operational contract for accessing Danish Grunddata registers through Datafordeler GraphQL and file download services. This manifest is a platform-level source contract used by dataset manifests such as CVR, DAR, BBR, and DAGI.",
    "research_question_links": [
      "How should an agent authenticate and paginate reliably across Datafordeler registers?",
      "Which query, timeout, and filterability constraints are common across GraphQL services?",
      "How should temporal semantics be handled consistently across register workflows?"
    ]
  },
  "provenance": {
    "source_origin": "Datafordeler platform and Grunddatamodel documentation",
    "acquisition_date": "2026-04-03",
    "licence": "Institutional Datafordeler agreement and register-specific terms",
    "source_manifest_refs": [
      "https://confluence.sdfi.dk/pages/viewpage.action?pageId=187105434",
      "https://confluence.sdfi.dk/pages/viewpage.action?pageId=193921410",
      "https://grunddatamodel.datafordeler.dk/domaenemodeller/",
      "data_sanctuary/shared/datafordeler_graphql_contract.md",
      "data_sanctuary/shared/time_semantics_shared.md",
      "TIME_IN_GIS_DAGI_STUDENT_NOTE.md"
    ]
  },
  "grounding_logic": {
    "type": "api",
    "uri": "https://graphql.datafordeler.dk/",
    "layer_filter": "register-specific",
    "crs": "EPSG:25832",
    "geometry_type": "NONE",
    "join_hints": []
  },
  "privacy_governance": {
    "gdpr_classification": "Public",
    "retention_period": "Project duration + 5 years",
    "access_requirements": "Institutional API key and explicit register permissions",
    "ethical_risks": [
      "Incorrect time interpretation can create legally misleading outputs.",
      "Implicit filter assumptions can exclude relevant entities without traceability."
    ]
  },
  "sanitisation_rituals": [
    "Validate endpoint and permission before large extraction jobs.",
    "Record executed query text and pagination strategy in project logs.",
    "Declare whether valid time and/or transaction time are applied."
  ],
  "attributes": [
    {
      "name": "apikey",
      "logical_type": "Nominal",
      "meaning": "Authentication token supplied as query parameter for Datafordeler GraphQL endpoints.",
      "provenance_level": "source"
    },
    {
      "name": "virkningstid",
      "logical_type": "Interval",
      "meaning": "GraphQL query time parameter for real-world validity axis where supported.",
      "provenance_level": "source"
    },
    {
      "name": "registreringstid",
      "logical_type": "Interval",
      "meaning": "GraphQL query time parameter for transaction/registration axis where supported.",
      "provenance_level": "source"
    }
  ],
  "agent_hints": {
    "recommended_filters": [
      "Start with small page size and iterate using pageInfo cursor.",
      "Confirm filterability of fields in register-specific FilterInput type before query execution.",
      "Use staged extraction when one query exceeds timeout limits."
    ],
    "known_pitfalls": [
      "All Datafordeler GraphQL queries use Relay cursor pagination (edges { node { } } / pageInfo { hasNextPage endCursor }). There is no page/pagesize argument — these will return an argument-not-found error.",
      "A returned field is not always a filterable field. Fields must appear in the register-specific *FilterInput type to be usable in where: { }.",
      "Do not pass fields such as kommunekode as top-level query arguments — they must go inside where: { kommunekode: { eq: \"...\" } }.",
      "Most entities require virkningstid or registreringstid — omitting both causes error DAF-GQL-0009.",
      "Some broad queries fail with timeout code HC0045. For high-cost entities (weight 5000) keep first ≤ 200.",
      "A valid key can still fail if register-specific permissions are not enabled for that register."
    ],
    "quality_notes": [
      "This platform manifest should be referenced by all dataset manifests using Datafordeler APIs.",
      "Dataset manifests remain responsible for register-specific entities, vocabularies, and join semantics."
    ]
  },
  "shared_contract_refs": [
    "data_sanctuary/shared/datafordeler_graphql_contract.md",
    "data_sanctuary/shared/time_semantics_shared.md",
    "TIME_IN_GIS_DAGI_STUDENT_NOTE.md",
    "data_sanctuary/sources/datafordeler.graphql.services.manifest.v1.json"
  ],
  "execution_contract": {
    "interface_type": "mixed",
    "auth": {
      "scheme": "apikey",
      "location": "query_param",
      "parameter_name": "apikey",
      "required_permissions": [
        "register-specific access rights"
      ]
    },
    "pagination": {
      "style": "cursor",
      "page_size_param": "first",
      "cursor_param": "after",
      "recommended_page_size": 200,
      "max_page_size": 1000
    },
    "timeouts": {
      "server_timeout_seconds": 60,
      "retry_strategy": "reduce page size and split extraction into staged queries when timeout occurs"
    },
    "time_parameters": {
      "supports_virkningstid": true,
      "supports_registreringstid": true,
      "default_query_mode": "register_default"
    },
    "filterability_notes": [
      "Returned fields are not always filterable in FilterInput.",
      "Validate FilterInput type before constructing where clauses."
    ],
    "known_error_codes": [
      "401",
      "400",
      "HC0045"
    ]
  },
  "platform_links": [
    "https://semanticgis.dk"
  ],
  "resource_scope": "platform"
}
