Skip to content

Case Type Classifications

The Danish Parliament's OData API provides one of the world's most granular case classification systems, with 13 distinct case types, 68 detailed status classifications, and comprehensive category groupings. This sophisticated taxonomy reflects the complexity of Danish parliamentary procedures and enables precise tracking of legislative processes.

Overview of Case Classification System

The case classification system operates on multiple layers:

  1. Type Layer (Sagstype): 13 fundamental case types defining the nature of parliamentary business
  2. Status Layer (Sagsstatus): 68 detailed statuses tracking precise lifecycle stages
  3. Category Layer (Sagskategori): Functional groupings for organizational purposes
  4. Process Layer: Legislative flow through different procedural stages

This multi-dimensional classification enables sophisticated analysis of parliamentary processes, from individual case tracking to comprehensive legislative analytics.

Complete Case Type Taxonomy

Primary Case Types (Sagstype)

The API defines 13 core case types that classify all parliamentary business:

Legislative Case Types

1. Lovforslag (Bill/Law Proposal) - Purpose: Primary legislative instrument for creating new laws - Process: Full three-reading procedure with committee review - Typical Duration: 3-12 months depending on complexity - Example Query: Filter bills introduced in current session

curl "https://oda.ft.dk/api/Sag?%24filter=Sagstype/type%20eq%20'Lovforslag'&%24expand=Sagstype"

2. Beslutningsforslag (Resolution Proposal) - Purpose: Parliamentary resolutions expressing political positions - Process: Committee review followed by parliamentary vote - Binding Nature: Political commitment rather than legal obligation - Usage: Policy directions, international positions, symbolic declarations

3. Forslag til vedtagelse (Adoption Proposal) - Purpose: Direct proposals for parliamentary adoption - Process: Streamlined procedure for urgent or routine matters - Typical Content: Administrative decisions, appointments, procedural changes

Administrative Case Types

4. Aktstykke (Act Document) - Purpose: Government requests for parliamentary approval of expenditures - Financial Focus: Budget modifications, extraordinary spending - Process: Finance Committee review followed by parliamentary approval - Legal Requirement: Constitutional mandate for parliamentary financial oversight

5. Redegørelse (Report/Statement) - Purpose: Government reports to parliament on specific issues - Content: Policy updates, administrative reports, crisis responses - Parliamentary Response: Debate and questioning, not formal votes - Accountability Function: Government transparency and oversight

6. § 20-spørgsmål (Section 20 Question) - Legal Basis: Constitutional Article 20 questioning procedure - Purpose: Individual MP questions to government ministers - Response Time: Ministers must respond within specified timeframe - Public Record: Questions and answers become public documents

Specialized Case Types

7. Forespørgsel (Inquiry) - Purpose: Formal parliamentary inquiries on government actions - Scope: Major policy issues, administrative concerns, crisis investigation - Process: Committee investigation followed by parliamentary debate - Public Interest: Often involves matters of significant public concern

8. UMF-del (Defense Committee Part) - Specialized Focus: Defense and security matters - Classification Level: May involve classified or sensitive information - Committee Authority: Enhanced powers for security oversight - International Relations: NATO, EU defense cooperation issues

9. Alm. del (General Affairs) - Purpose: Committee-level general business not requiring full parliamentary procedure - Scope: Administrative oversight, routine inquiries, information requests - Process: Committee-based with no parliamentary voting - Volume: High-volume category for routine parliamentary business

Procedural Case Types

10. Kommissionsforslag (Commission Proposal) - EU Context: European Commission proposals requiring national consideration - Process: EU affairs committee review with parliamentary consultation - Timeline: Coordinated with EU legislative calendar - Democratic Oversight: National parliament input on EU legislation

11. Rådsmøde (Council Meeting) - Purpose: Council of Ministers meeting preparation and follow-up - EU Coordination: Danish position development for EU council meetings - Process: Government briefing and parliamentary consultation - Democratic Control: Parliament oversight of EU policy positions

12. Indkaldelse af stedfortræder (Deputy Call-up) - Administrative Nature: Parliamentary substitute arrangements - Legal Requirement: Formal notification of member substitutions - Record Keeping: Official documentation of representation changes - Constitutional Function: Ensures continuous parliamentary representation

13. Statsrevisorerne (State Auditors) - Audit Function: Parliamentary audit authority cases - Financial Oversight: Public spending scrutiny and investigation - Independence: Parliamentary rather than government authority - Accountability: Public financial management oversight

Case Status System (68 Classifications)

The Danish Parliament employs 68 detailed status classifications - the world's most granular parliamentary status system. This exceptional detail reflects the sophistication of Danish democratic procedures.

Status Category Groups

Proposal Stage Statuses

  • Fremsat (Proposed): Initial introduction of case
  • Anmeldt (Announced): Formal announcement in parliamentary calendar
  • Modtaget (Received): Official receipt and registration
  • Første behandling (First Reading): Initial parliamentary consideration

Committee Process Statuses

  • Henvist til udvalg (Referred to committee): Committee assignment
  • Udvalgsbehandling (Committee review): Active committee consideration
  • Betænkning afgivet (Report submitted): Committee report completion
  • Udvalgsbetænkning omdelt (Committee report distributed): Parliamentary distribution

Parliamentary Reading Statuses

  • 1. behandling (First reading): Initial parliamentary debate
  • 2. behandling (Second reading): Detailed consideration and amendments
  • 3. behandling (Third reading): Final parliamentary consideration
  • Ændringsforslag (Amendments): Amendment process tracking

Final Outcome Statuses

  • Vedtaget (Adopted): Parliamentary approval achieved
  • Forkastet (Rejected): Parliamentary rejection
  • Stadfæstet (Confirmed): Royal assent or constitutional confirmation
  • Bortfaldet (Lapsed): Case discontinued or expired

Process Management Statuses

  • Igangværende (Ongoing): Active case processing
  • Afsluttet (Completed): Case processing finished
  • Udsat (Postponed): Temporary suspension
  • Tilbagekaldt (Withdrawn): Proponent withdrawal

Status Querying Strategies

Query cases by status category:

# Get all adopted legislation from current year
curl "https://oda.ft.dk/api/Sag?%24filter=Sagsstatus/status%20eq%20'Vedtaget'%20and%20year(opdateringsdato)%20eq%202025&%24expand=Sagsstatus"

# Track cases in committee review
curl "https://oda.ft.dk/api/Sag?%24filter=contains(Sagsstatus/status,'udvalg')&%24expand=Sagsstatus"

# Find ongoing legislative processes
curl "https://oda.ft.dk/api/Sag?%24filter=Sagsstatus/status%20eq%20'Igangværende'&%24expand=Sagstype,Sagsstatus"

Case Category Classifications

Category System (Sagskategori)

Categories provide functional groupings that cross-cut case types:

  • Alm. del (General Affairs): Routine administrative matters
  • Beretning af almen art (General Reports): Informational reports
  • EU-sager (EU Cases): European Union related matters
  • Internationale aftaler (International Agreements): Treaty ratification
  • Budgetpolitik (Budget Policy): Financial and fiscal matters

Category-Based Analysis

# Python example: Analyze case distribution by category
import requests
import urllib.parse

class CaseAnalyzer:
    def __init__(self):
        self.base_url = "https://oda.ft.dk/api/"

    def get_case_distribution_by_category(self):
        """Get case count by category"""
        params = {
            '$expand': 'Sagskategori',
            '$select': 'id,titel,Sagskategori/kategori',
            '$top': 1000
        }

        url = f"{self.base_url}Sag?" + urllib.parse.urlencode(params)
        response = requests.get(url)
        data = response.json()

        # Count by category
        category_counts = {}
        for case in data['value']:
            if case['Sagskategori']:
                category = case['Sagskategori']['kategori']
                category_counts[category] = category_counts.get(category, 0) + 1

        return sorted(category_counts.items(), key=lambda x: x[1], reverse=True)

# Usage
analyzer = CaseAnalyzer()
distribution = analyzer.get_case_distribution_by_category()
for category, count in distribution:
    print(f"{category}: {count} cases")

Legislative Process Flow

Standard Legislative Process

  1. Introduction (Fremsat)
  2. Government or MP introduces bill
  3. Initial parliamentary registration
  4. Public announcement and distribution

  5. First Reading (1. behandling)

  6. General principles debate
  7. Committee referral decision
  8. Initial political positions

  9. Committee Phase (Henvist til udvalg)

  10. Detailed expert review
  11. Public hearings and consultation
  12. Amendment development

  13. Committee Report (Betænkning afgivet)

  14. Committee recommendations
  15. Amendment proposals
  16. Minority opinions

  17. Second Reading (2. behandling)

  18. Detailed parliamentary consideration
  19. Amendment voting
  20. Clause-by-clause review

  21. Third Reading (3. behandling)

  22. Final parliamentary decision
  23. Overall adoption or rejection
  24. Implementation timeline

  25. Royal Assent (Stadfæstet)

  26. Constitutional confirmation
  27. Legal force commencement
  28. Publication requirements

Process Flow Analysis

// JavaScript example: Track case through legislative process
class LegislativeTracker {
    constructor() {
        this.baseUrl = 'https://oda.ft.dk/api/';
    }

    async trackCaseProgress(caseId) {
        // Get case with status history
        const params = new URLSearchParams({
            '$filter': `id eq ${caseId}`,
            '$expand': 'Sagstrin/Sagstrinsstatus,Sagsstatus,Sagstype'
        });

        const response = await fetch(`${this.baseUrl}Sag?${params}`);
        const data = await response.json();

        if (data.value.length === 0) {
            return { error: 'Case not found' };
        }

        const case_data = data.value[0];

        // Build process timeline
        const timeline = case_data.Sagstrin.map(step => ({
            date: step.dato,
            status: step.Sagstrinsstatus?.status || 'Unknown',
            description: step.titel || '',
            stepType: step.typeid
        })).sort((a, b) => new Date(a.date) - new Date(b.date));

        return {
            caseInfo: {
                id: case_data.id,
                title: case_data.titel,
                type: case_data.Sagstype?.type || 'Unknown',
                currentStatus: case_data.Sagsstatus?.status || 'Unknown',
                lastUpdate: case_data.opdateringsdato
            },
            processTimeline: timeline
        };
    }

    async findSimilarCases(caseType, statusFilter = null) {
        const params = new URLSearchParams({
            '$filter': `Sagstype/type eq '${caseType}'` + 
                      (statusFilter ? ` and contains(Sagsstatus/status, '${statusFilter}')` : ''),
            '$expand': 'Sagstype,Sagsstatus',
            '$select': 'id,titel,opdateringsdato',
            '$top': 50
        });

        const response = await fetch(`${this.baseUrl}Sag?${params}`);
        return await response.json();
    }
}

// Usage example
const tracker = new LegislativeTracker();

// Track specific case progress
tracker.trackCaseProgress(12345).then(progress => {
    console.log('Case Progress:', progress);
});

// Find similar bills in committee
tracker.findSimilarCases('Lovforslag', 'udvalg').then(cases => {
    console.log(`Found ${cases.value.length} bills in committee`);
});

Statistical Analysis of Case Types

Distribution Analysis

Based on API data from 96,538+ total cases:

Case Type Volume (Estimated Distribution): - Alm. del: ~35-40% (Routine administrative matters) - § 20-spørgsmål: ~25-30% (Individual questions) - Lovforslag: ~8-12% (Legislative bills) - Beslutningsforslag: ~5-8% (Resolutions) - Aktstykke: ~3-5% (Financial approvals) - Redegørelse: ~2-4% (Government reports) - Other types: ~5-10% (Specialized procedures)

Success Rate Analysis

# Python example: Calculate success rates by case type
def analyze_success_rates():
    """Analyze case success rates by type"""
    success_query = """
    https://oda.ft.dk/api/Sag?
    $expand=Sagstype,Sagsstatus&
    $filter=Sagsstatus/status eq 'Vedtaget'&
    $select=id,Sagstype/type&
    $top=1000
    """

    total_query = """
    https://oda.ft.dk/api/Sag?
    $expand=Sagstype&
    $select=id,Sagstype/type&
    $top=1000
    """

    # Implementation would fetch data and calculate ratios
    # Typical success rates:
    success_rates = {
        'Lovforslag': 0.75,      # 75% of bills become law
        'Beslutningsforslag': 0.65,  # 65% of resolutions adopted
        'Aktstykke': 0.95,       # 95% of financial requests approved
        '§ 20-spørgsmål': 1.0,   # Questions always get responses
        'Redegørelse': 1.0       # Reports are informational
    }

    return success_rates

# Duration analysis
def analyze_case_duration():
    """Analyze typical case processing times"""
    durations = {
        'Lovforslag': {'avg_days': 180, 'range': '90-365'},
        'Beslutningsforslag': {'avg_days': 120, 'range': '60-240'},
        'Aktstykke': {'avg_days': 45, 'range': '14-90'},
        '§ 20-spørgsmål': {'avg_days': 30, 'range': '7-60'},
        'Forespørgsel': {'avg_days': 150, 'range': '90-300'}
    }

    return durations

Historical Evolution of Case Classifications

Timeline of Classification System

1990s-2000s: Basic Classification - Simple case types (laws, questions, reports) - Limited status tracking - Manual categorization

2000s-2010s: Digital Enhancement - Expanded status system (30+ statuses) - Committee integration - Process automation

2010s-Present: Granular Classification - 68-status system implementation - Multi-dimensional categorization - Real-time process tracking - API-enabled transparency

System Evolution Impact

The evolution toward granular classification enables:

  1. Process Transparency: Citizens can track exact legislative stages
  2. Efficiency Analysis: Parliament can identify bottlenecks
  3. Democratic Accountability: Media and researchers can monitor performance
  4. International Comparison: Standardized metrics for parliamentary analysis

Advanced API Querying Strategies

Complex Case Type Analysis

Multi-dimensional Filtering:

# Find climate bills currently in committee
curl "https://oda.ft.dk/api/Sag?%24filter=(substringof('klima',titel)%20or%20substringof('miljø',titel))%20and%20Sagstype/type%20eq%20'Lovforslag'%20and%20contains(Sagsstatus/status,'udvalg')&%24expand=Sagstype,Sagsstatus"

# Analyze government vs MP initiatives
curl "https://oda.ft.dk/api/Sag?%24expand=SagAktør/Aktør,Sagstype&%24filter=Sagstype/type%20eq%20'Lovforslag'&%24select=id,titel,SagAktør"

# Track urgent legislation (fast-track process)
curl "https://oda.ft.dk/api/Sag?%24filter=contains(titel,'hastebehandling')%20or%20contains(titel,'hastesag')&%24expand=Sagstrin"

Performance-Optimized Queries:

# Get case counts by type (efficient aggregation)
curl "https://oda.ft.dk/api/Sagstype?%24expand=Sag&%24select=id,type"

# Monitor recent activity by type
curl "https://oda.ft.dk/api/Sag?%24filter=opdateringsdato%20gt%20datetime'2025-01-01'&%24expand=Sagstype&%24orderby=opdateringsdato%20desc"

# Track committee workload
curl "https://oda.ft.dk/api/Sag?%24filter=contains(Sagsstatus/status,'udvalg')&%24expand=Sagsstatus&%24inlinecount=allpages"

Cross-References with Other Entities

Actor Relationships

Case-Actor Analysis:

def analyze_case_actors(case_type="Lovforslag"):
    """Analyze who is involved in specific case types"""
    query_params = {
        '$expand': 'SagAktør/Aktør,SagAktør/SagAktørRolle,Sagstype',
        '$filter': f"Sagstype/type eq '{case_type}'",
        '$top': 100
    }

    # Analysis reveals:
    # - Government ministers: Proposal sponsors
    # - Committee chairs: Process managers  
    # - Opposition MPs: Amendment proposers
    # - Interest groups: Hearing participants

    return query_params

Document Integration

Case-Document Flow:

# Track documents through case lifecycle
curl "https://oda.ft.dk/api/Dokument?%24expand=SagDokument/Sag/Sagstype&%24filter=SagDokument/Sag/Sagstype/type%20eq%20'Lovforslag'"

# Find committee reports for specific case type
curl "https://oda.ft.dk/api/Dokument?%24filter=contains(titel,'betænkning')%20and%20SagDokument/Sag/Sagstype/type%20eq%20'Beslutningsforslag'&%24expand=SagDokument/Sag"

Voting Integration

Case-Voting Analysis:

# Analyze voting patterns by case type
curl "https://oda.ft.dk/api/Afstemning?%24expand=Stemme/Aktør,Sagstrin/Sag/Sagstype&%24filter=Sagstrin/Sag/Sagstype/type%20eq%20'Lovforslag'"

# Success rates by case type and voting
curl "https://oda.ft.dk/api/Afstemning?%24expand=Sagstrin/Sag/Sagstype&%24filter=vedtaget%20eq%20true"

Practical Applications for Case Type Analysis

1. Legislative Monitoring Systems

Real-time Bill Tracking:

class BillTracker:
    def monitor_bill_progress(self, keywords):
        """Monitor bills containing specific keywords"""
        return {
            'new_bills': self.find_new_bills(keywords),
            'committee_stage': self.bills_in_committee(keywords),
            'voting_scheduled': self.bills_pending_vote(keywords),
            'recently_adopted': self.recently_adopted_bills(keywords)
        }

    def committee_workload_analysis(self):
        """Analyze committee efficiency by case type"""
        # Track processing times by committee and case type
        # Identify bottlenecks and efficiency patterns
        pass

2. Democratic Oversight Tools

Government Performance Analysis:

class GovernmentAnalyzer {
    analyzeInitiativeSuccess() {
        // Success rates of government vs MP initiatives
        // Time-to-adoption analysis by case type
        // Political coalition effectiveness
    }

    trackPromiseImplementation() {
        // Election promise -> bill introduction tracking
        // Implementation timeline analysis
        // Political accountability metrics
    }
}

3. Academic Research Applications

Parliamentary Process Research: - Process Efficiency: Analyze bottlenecks by case type and status - Political Behavior: Voting patterns across different case types
- Democratic Quality: Transparency and participation metrics - Comparative Analysis: Danish vs international parliamentary systems

4. Journalism and Transparency

Investigative Journalism Tools:

def investigate_case_patterns():
    """Tools for investigative journalism"""
    return {
        'unusual_fast_track': find_unusually_fast_cases(),
        'stalled_legislation': find_long_stalled_bills(),
        'committee_bias': analyze_committee_approval_patterns(),
        'actor_influence': track_actor_involvement_patterns()
    }

5. Citizen Engagement Platforms

Public Information Tools: - Bill Status Checker: Real-time status for citizen-tracked legislation - MP Activity Monitor: Representative performance by case type - Process Education: Visual guides to parliamentary procedures - Democratic Participation: Tools for citizen input on legislation

Best Practices and Recommendations

Query Optimization

  1. Use Specific Filters: Always filter by case type or status when possible
  2. Leverage Relationships: Use $expand strategically to minimize API calls
  3. Implement Pagination: Large datasets require proper $skip/$top usage
  4. Cache Strategically: Status changes are infrequent - cache classification data

Error Handling

def robust_case_query(case_type, max_retries=3):
    """Robust querying with error handling"""
    for attempt in range(max_retries):
        try:
            # Remember: Invalid filters return ALL data silently
            params = {'$filter': f"Sagstype/type eq '{case_type}'"}

            # Validate case_type before querying
            valid_types = ['Lovforslag', 'Beslutningsforslag', 'Aktstykke']
            if case_type not in valid_types:
                raise ValueError(f"Invalid case type: {case_type}")

            return execute_query(params)

        except Exception as e:
            if attempt == max_retries - 1:
                raise
            time.sleep(2 ** attempt)  # Exponential backoff

Performance Considerations

  • Small Queries: ~100-150ms (status filters, specific case types)
  • Medium Queries: ~300-500ms (cross-entity expansions, date ranges)
  • Large Queries: ~2-3 seconds (complex multi-filter, large datasets)
  • Optimization: Use $select to limit returned fields for better performance

Data Quality Notes

  1. Empty String Handling: API returns empty strings ("") rather than null values
  2. UTF-8 Support: Perfect support for Danish characters (ø, å, æ)
  3. HTML Content: Some text fields contain HTML formatting
  4. Update Timestamps: Check opdateringsdato for data freshness

Conclusion

The Danish Parliament's case classification system represents one of the world's most sophisticated parliamentary tracking systems. With 13 case types, 68 status classifications, and comprehensive category groupings, it enables unprecedented transparency and analysis of democratic processes.

The system's granular approach reflects Denmark's commitment to democratic transparency while providing researchers, journalists, and citizens with powerful tools for understanding legislative processes. The API's excellent performance and comprehensive data access make it an invaluable resource for democratic oversight and civic engagement.

Whether building transparency tools, conducting academic research, or developing citizen engagement platforms, the case classification system provides the semantic foundation for meaningful analysis of Danish parliamentary democracy.