diff --git a/db_schema.sql b/db_schema.sql
index 43ad82ee8fb90635da6afe94d8e7ff19db7530b8..c1570e44f4003323ca541f159badb8fa0adec4cd 100644
--- a/db_schema.sql
+++ b/db_schema.sql
@@ -230,6 +230,24 @@ CREATE TABLE IF NOT EXISTS `sorterrorlog_data` (
   `time_created` datetime NOT NULL
 );
 
+CREATE TABLE IF NOT EXISTS `worker` (
+`hostname` text NOT NULL PRIMARY KEY,
+  `last_ping` datetime NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS `jobs` (
+`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+  `type` text NOT NULL,
+  `priority` INTEGER NOT NULL DEFAULT 0,
+  `state` text NOT NULL DEFAULT 'ready',
+  `time_finished` datetime DEFAULT '',
+  `time_created` datetime NOT NULL,
+  `last_ping` datetime NOT NULL DEFAULT '',
+  `worker` text DEFAULT NULL,
+  `data` text NOT NULL DEFAULT '{}',
+  `status` text NOT NULL DEFAULT '{}'
+);
+
 CREATE VIEW IF NOT EXISTS `courses` AS select * from `courses_data` where (not(`courses_data`.`deleted`));
 CREATE VIEW IF NOT EXISTS `lectures` AS select `lectures_data`.* from `lectures_data` join `courses_data` on (`courses_data`.`id` = `course_id`) where (not(`lectures_data`.`deleted` or `courses_data`.`deleted`));
 CREATE VIEW IF NOT EXISTS `videos` AS select `videos_data`.* from `videos_data` join `lectures_data` on (`lectures_data`.`id` = `lecture_id`) join `courses_data` on (`courses_data`.`id` = `course_id`) where (not(`videos_data`.`deleted` or `lectures_data`.`deleted` or `courses_data`.`deleted`));
diff --git a/jobs.py b/jobs.py
index 8fea7a8b3a30ab107786c7a235a09319b13c9c5c..c5d6442f705f6bc0bb6f299109f529c02c166d8d 100644
--- a/jobs.py
+++ b/jobs.py
@@ -1,15 +1,51 @@
 from server import *
 import traceback
+import json
 
 @app.route('/jobs/overview')
 @register_navbar('Jobs', iconlib='fa',  icon='suitcase')
 @mod_required
 def jobs_overview():
-	# todo
-	return render_template('base.html')
+	worker = query('SELECT * FROM worker ORDER BY last_ping DESC')
+	jobs = query('SELECT * FROM jobs')
+	return render_template('jobs_overview.html',worker=worker,jobs=jobs)
 
-@app.route('/jobs/api', methods=['GET', 'POST'])
-@mod_required
-def jobs_api():
-	# todo
-	return render_template('base.html')
+def jobs_api_token_required(func):
+	@wraps(func)
+	def decorator(*args, **kwargs):
+		if 'apikey' in request.values:
+			token = request.values['apikey']
+		elif request.get_json() and ('apikey' in request.get_json()):
+			token = request.get_json()['apikey']
+		else:
+			token = None
+		
+		if not token == config['JOBS_API_KEY']:
+			return 'Permission denied', 403
+		else:
+			return func(*args, **kwargs)
+	return decorator
+
+def date_json_handler(obj):
+	return obj.isoformat() if hasattr(obj, 'isoformat') else obj
+
+@app.route('/jobs/api/ping', methods=['GET', 'POST'])
+@jobs_api_token_required
+def jobs_ping():
+	hostname = request.values['host']
+	query('INSERT OR REPLACE INTO worker (hostname, last_ping) values (?, ?)',hostname,datetime.now())
+	return 'OK',200
+
+@app.route('/jobs/api/schedule', methods=['POST'])
+@jobs_api_token_required
+def jobs_schedule():
+	hostdata =  request.get_json()
+	print(hostdata)
+	if not hostdata:
+		return 'no data', 500
+	jobtypes = hostdata['jobtypes'] if 'jobtypes' in hostdata else []
+	for i in query('SELECT * FROM jobs WHERE state = "ready" ORDER BY priority DESC'):
+		if i['type'] in hostdata['jobtypes'].split(','):
+			job=i
+			break
+	return Response(json.dumps(job, default=date_json_handler),  mimetype='application/json')
diff --git a/server.py b/server.py
index 1bf0958f8d2701047f4fcf300b141373c5366f82..62918f7105c3d93daaad5c77ef8be8393d4bd49a 100644
--- a/server.py
+++ b/server.py
@@ -10,7 +10,6 @@ import random
 import sched
 import traceback
 import string
-import traceback
 
 app = Flask(__name__)
 
diff --git a/sorter.py b/sorter.py
index f7473b10946cdbe8b1d352e102306fad7859eb66..b17ccb4c9b69ea92bb314f6b6b4e4736e641a781 100644
--- a/sorter.py
+++ b/sorter.py
@@ -33,7 +33,25 @@ def insert_video(lectureid,dbfilepath,filepath,fileformatid):
 		(?,0,?,?,"","","",?,?,?,?,"",?)''',
 		lectureid, dbfilepath, fileformatid, datetime.now(), datetime.now(), datetime.now(), -1, os.stat(filepath).st_size)
 	query('INSERT INTO sortlog (lecture_id,video_id,path,`when`) VALUES (?,?,?,?)', lectureid, video_id, dbfilepath, datetime.now())
+	schedule_thumbnail(lectureid)
 
+def schedule_thumbnail(lectureid):
+	exists = query('SELECT * FROM jobs WHERE data LIKE ?','%"lectureid": "'+str(lectureid)+'"%' )
+	if exists:
+		return
+	path = query('SELECT path FROM videos WHERE lecture_id')
+	videos = query('''
+			SELECT videos.path
+			FROM videos
+			JOIN formats ON (videos.video_format = formats.id)
+			WHERE videos.lecture_id = ?
+			ORDER BY formats.prio DESC''', lectureid )
+	if videos:
+		path = videos[0]['path']
+	else:
+		return
+	data = '{"lectureid": "'+str(lectureid)+'", "path": "'+path+'"}'
+	query('INSERT INTO jobs (type, data, time_created) VALUES ("thumbnail", ?, ?)', data, datetime.now());
 
 @app.route('/sort/now')
 @mod_required
diff --git a/templates/jobs_overview.html b/templates/jobs_overview.html
new file mode 100644
index 0000000000000000000000000000000000000000..a5af33befc55b799de503eb0751752f254aba51d
--- /dev/null
+++ b/templates/jobs_overview.html
@@ -0,0 +1,87 @@
+{% extends "base.html" %}
+{% block content %}
+<div class="panel-group">
+	<div class="panel panel-default">
+		<div class="panel-heading">
+				<h1 class="panel-title">
+					Worker
+				</h1>
+		</div>
+		<div class="panel-collapse collapse in">
+			<div class="panel-body">
+				<table class="table">
+				<tr>
+					<th>Hostname</th>
+					<th>letzter Ping</th>
+				</tr>
+					{% for i in worker %}
+						{% set td = (datetime.now()-(i.last_ping) ) %}
+						
+						{% if td < timedelta(seconds=10) %}
+							<tr class="success">
+						{% elif td < timedelta(seconds=30) %}
+							<tr class="warning">
+						{% else %}
+							<tr class="danger">
+						{% endif %}
+							<td>{{i.hostname}}</td>
+							<td>{{i.last_ping}}</td>
+						</tr>
+					{% endfor %}
+				</table>
+			</div>
+		</div>
+	</div>
+	<div class="panel panel-default">
+		<div class="panel-heading">
+				<h1 class="panel-title">
+					Jobs
+				</h1>
+		</div>
+		<div class="panel-collapse collapse in">
+			<div class="panel-body">
+				<table class="table">
+				<tr>
+					<th>ID</th>
+					<th>Type</th>
+					<th>Priority</th>
+					<th>Worker</th>
+					<th>letzter Ping</th>
+					<th>State</th>
+					<th>Eingereiht am</th>
+					<th>Fertig geworden am</th>
+					<th>Daten</th>
+				</tr>
+					{% for i in jobs %}
+						{% if i.last_ping %}
+							{% set td = (datetime.now()-(i.last_ping) ) %}
+						{% else %}
+							{% set td = -1 %}
+						{% endif %}
+
+						{% if td == -1 %}
+							<tr>
+						{% elif td < timedelta(seconds=20) %}
+							<tr class="success">
+						{% elif td < timedelta(seconds=60) %}
+							<tr class="warning">
+						{% else %}
+							<tr class="danger">
+						{% endif %}
+							<td>{{i.id}}</td>
+							<td>{{i.type}}</td>
+							<td>{{i.priority}}</td>
+							<td>{{i.worker}}</td>
+							<td>{{i.last_ping}}</td>
+							<td>{{i.state}}</td>
+							<td>{{i.time_created}}</td>
+							<td>{{i.time_finished}}</td>
+							<td>{{i.data}}</td>
+						</tr>
+					{% endfor %}
+				</table>
+			</div>
+		</div>
+	</div>
+</div>
+{% endblock %}