diff --git a/app/jobs/pretalx/import_job.rb b/app/jobs/pretalx/import_job.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6e5c8b52bbc5f5939b633de7e7a82b3eb87c77ab
--- /dev/null
+++ b/app/jobs/pretalx/import_job.rb
@@ -0,0 +1,59 @@
+require 'httparty'
+
+module Pretalx
+  # See https://c3voc.de/wiki/schedule for more information about the format
+  # Schema: https://c3voc.de/schedule/schema.json
+  class ImportJob < ApplicationJob
+    queue_as :default
+    include ActionView::Helpers
+
+    def import_schedule(conference, url)
+      response = HTTParty.get(url)
+      response.success? or return Rails.logger.error "Failed to fetch schedule from #{url}"
+
+      schedule = JSON.parse(response.body)
+      # We keep a local hash of the stages, because the sessions reference stages by name instead of id
+      stages = {}
+      schedule['schedule']['conference']['rooms'].each do |stage_data|
+        stages[stage_data['name']] = Stage.find_or_initialize_by(conference:, ref_id: stage_data['guid']).tap do |stage_|
+          stage_.name = stage_data['name']
+          stage_.save!
+        end
+      end
+      schedule['schedule']['conference']['days'].each do |day_data|
+        day_data['rooms'].each do |stage_name, stage_data|
+          print stage_name + "\n=====================\n"
+          stage = stages[stage_name]
+          stage_data.each do |session_data|
+            Session.find_or_initialize_by(conference:, ref_id: session_data['guid']).tap do |session|
+              session.stage = stage
+              session.title = session_data['title']
+              session.language = session_data['language']
+              session.description = simple_format(session_data['abstract']) + simple_format(session_data['description'])
+              session.session_format = session_data['type']
+              session.track = session_data['track']
+              session.starts_at = session_data['date']
+              hours, minutes = session_data['duration'].split(":").map(&:to_i)
+              session.ends_at = session.starts_at + hours.hours + minutes.minutes
+              session.url = session_data['url']
+              session.speakers = session_data['persons'].map do |speaker_data|
+                Speaker.find_or_initialize_by(ref_id: speaker_data['guid'], conference:).tap do |speaker|
+                  speaker.name = speaker_data['name']
+                  speaker.description = simple_format(speaker_data['biography'])
+                  speaker.save!
+                end
+              end
+              session.save!
+            end
+          end
+        end
+      end
+    end
+
+    def perform(conference_slug, *args)
+      conference = Conference.find_by(slug: conference_slug)
+      import_schedule(conference, conference.data['schedule_url'])
+      RevisionSet.create!(conference:)
+    end
+  end
+end
diff --git a/db/seeds.rb b/db/seeds.rb
index f9464ced7d5facd4dcc22b7efd314d3f1113bbba..5cdce4a7c7dbb58aa2f26513a0975a935823077f 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -34,7 +34,19 @@ Conference.find_or_create_by!(slug: "rp2024") do |c|
   c.location = "STATION Berlin"
 end
 
-%w[Teal hdsjulian Sophie bergpiratin sblsg Max aerowaffle ningwie Senana ToniHDS].each do |username|
+Conference.find_or_create_by!(slug: "37c3") do |c|
+  c.name = "37th Chaos Communication Congress"
+  c.time_zone = "Berlin"
+  c.starts_at = DateTime.parse("27 December 2023 10:30 CEST")
+  c.ends_at = DateTime.parse("30 December 2023 19:00 CEST")
+  c.data = {
+    "schedule_url" => "https://fahrplan.events.ccc.de/congress/2023/fahrplan/schedule.json"
+  }
+  c.import_job_class = "pretalx"
+  c.location = "Congress Center Hamburg"
+end
+
+%w[tribut Teal hdsjulian Sophie bergpiratin sblsg Max aerowaffle ningwie Senana ToniHDS].each do |username|
   User.find_or_create_by(name: username) do |u|
     u.email = "c3lingo+#{username}@x.moeffju.net"
   end