diff --git a/doc/config.rst b/doc/config.rst
index 3f31f863faac90889a5a69f4416c2c7669553050..1df8eea55cd3efff6c9e3a1bd1bb2c9f5290812a 100644
--- a/doc/config.rst
+++ b/doc/config.rst
@@ -184,6 +184,14 @@ REVERSE_PROXIED
 
   `Default value:` `False`
 
+.. _config-website-root-url:
+
+WEBSITE_ROOT_URL
+  URL to the website root (without trailing slash). Used for generating
+  download links in the batch scheduler.
+
+  `Default value:` `None`
+
 .. _config-soap-wsdl-url:
 
 SOAP_WSDL_URL
diff --git a/doc/deploy.rst b/doc/deploy.rst
index ab75f0e80f43f860e14ba862771569b049360f76..81026858dec117adc8a612a2dadd5fc4b56c8cdc 100644
--- a/doc/deploy.rst
+++ b/doc/deploy.rst
@@ -30,6 +30,7 @@ settings:
 - :ref:`EMAIL <config-email>`
 - :ref:`DEBUG <config-debug>`
 - :ref:`CACHE_DIR <config-cache-dir>`
+- :ref:`WEBSITE_ROOT_URL <config-website-root-url>`
 - :ref:`SOAP_WSDL_URL <config-soap-wsdl-url>`
 - :ref:`JSON_ROOT_URL <config-json-root-url>`
 - :ref:`REVERSE_PROXIED <config-reverse-proxied>`
diff --git a/mutalyzer/Scheduler.py b/mutalyzer/Scheduler.py
index f3ad60e6d86331722752e957402d5b17f45ab6d5..d6d96bb531cacd4c6faec963354dbfd3c0d78e7f 100644
--- a/mutalyzer/Scheduler.py
+++ b/mutalyzer/Scheduler.py
@@ -33,6 +33,7 @@ from mutalyzer.grammar import Grammar
 from mutalyzer.output import Output
 from mutalyzer.mapping import Converter
 from mutalyzer import Retriever           # Retriever.Retriever
+from mutalyzer import website
 
 
 __all__ = ["Scheduler"]
@@ -83,7 +84,7 @@ class Scheduler() :
         return not self.__run
     #stopped
 
-    def __sendMail(self, mailTo, url) :
+    def __sendMail(self, mailTo, result_id):
         """
         Send an e-mail containing an url to a batch job submitter.
 
@@ -91,8 +92,8 @@ class Scheduler() :
 
         @arg mailTo: The batch job submitter
         @type mailTo: unicode
-        @arg url: The url containing the results
-        @type url: unicode
+        @arg result_id: Identifier for the job result.
+        @type result_id: unicode
         """
         if settings.TESTING:
             return
@@ -105,6 +106,9 @@ class Scheduler() :
         #TODO: Handle Connection errors in a try, except clause
         #Expected errors: socket.error
 
+        download_url = website.url_for('batch_job_result',
+                                       result_id=result_id)
+
         message = MIMEText("""Dear submitter,
 
 The batch operation you have submitted, has been processed successfully.
@@ -116,7 +120,7 @@ Thanks for using Mutalyzer.
 
 
 With kind regards,
-Mutalyzer batch scheduler""" % url)
+Mutalyzer batch scheduler""" % download_url)
 
         message["Subject"] = "Result of your Mutalyzer batch job"
         message["From"] = settings.EMAIL
@@ -367,10 +371,6 @@ Mutalyzer batch scheduler""" % url)
             # Group batch jobs by email address and retrieve the oldest for
             # each address. This improves fairness when certain users have
             # many jobs.
-            # Note that batch jobs submitted via the webservices all have the
-            # same email address, so they are effectively throttled as if all
-            # from the same user. Adapting the webservices to also allow
-            # setting an email address is future work.
             batch_jobs = BatchJob.query.filter(BatchJob.id.in_(
                 session.query(func.min(BatchJob.id)).group_by(BatchJob.email))
             ).all()
@@ -403,7 +403,7 @@ Mutalyzer batch scheduler""" % url)
                 else:
                     print ('Job %s finished, email %s file %s'
                            % (batch_job.id, batch_job.email, batch_job.id))
-                    self.__sendMail(batch_job.email, batch_job.download_url)
+                    self.__sendMail(batch_job.email, batch_job.result_id)
                     session.delete(batch_job)
                     session.commit()
     #process
@@ -729,8 +729,7 @@ Mutalyzer batch scheduler""" % url)
                      "Finished SNP converter batch rs%s" % cmd)
     #_processSNP
 
-    def addJob(self, email, queue, columns, job_type, argument=None,
-               create_download_url=None):
+    def addJob(self, email, queue, columns, job_type, argument=None):
         """
         Add a job to the Database and start the BatchChecker.
 
@@ -744,18 +743,12 @@ Mutalyzer batch scheduler""" % url)
         @type job_type:
         @arg argument:          Batch Arguments, for now only build info
         @type argument:
-        @arg create_download_url: Function accepting a result_id and returning
-                                  the URL for downloading the batch job
-                                  result. Can be None.
-        @type create_download_url: function
 
         @return: result_id
         @rtype:
         """
         # Add jobs to the database
         batch_job = BatchJob(job_type, email=email, argument=argument)
-        if create_download_url:
-            batch_job.download_url = create_download_url(batch_job.result_id)
         session.add(batch_job)
 
         for i, inputl in enumerate(queue):
diff --git a/mutalyzer/__init__.py b/mutalyzer/__init__.py
index 77702d623de34affc80371de321ae5e726fd37db..412b0a816717d8cd76aa51963d41dc65474045a7 100644
--- a/mutalyzer/__init__.py
+++ b/mutalyzer/__init__.py
@@ -28,7 +28,7 @@ __date__ = '1 Oct 2015'
 __version__ = '.'.join(__version_info__)
 __author__ = 'Leiden University Medical Center'
 __contact__ = 'humgen@lumc.nl'
-__homepage__ = 'http://mutalyzer.nl'
+__homepage__ = 'https://mutalyzer.nl'
 
 
 NOMENCLATURE_VERSION_INFO = ('2', '0')
diff --git a/mutalyzer/config/default_settings.py b/mutalyzer/config/default_settings.py
index 93d9d42b579dc679ee41bec84f9fde128f1d7af6..4007fd0a5fc819099af9454d49b0e93153dfde36 100644
--- a/mutalyzer/config/default_settings.py
+++ b/mutalyzer/config/default_settings.py
@@ -69,6 +69,10 @@ BATCH_JOBS_ERROR_THRESHOLD = 0.05
 # (in seconds).
 NEGATIVE_LINK_CACHE_EXPIRATION = 60 * 60 * 24 * 30
 
+# URL to the website root (without trailing slash). Used for generating
+# download links in the batch scheduler.
+WEBSITE_ROOT_URL = None
+
 # URL to the SOAP webservice WSDL document. Used to build the WSDL document
 # and for linking to it from the documentation page on the website.
 SOAP_WSDL_URL = None
diff --git a/mutalyzer/services/rpc.py b/mutalyzer/services/rpc.py
index 508cd90530491ea8c0448ee2134fad35ab5c4b4f..3d3570ed69fb62484bc270d55e6b2508c5fba4db 100644
--- a/mutalyzer/services/rpc.py
+++ b/mutalyzer/services/rpc.py
@@ -77,7 +77,7 @@ class MutalyzerService(ServiceBase):
         Submit a batch job.
 
         Input and output file formats for batch jobs are explained on the
-        website <https://mutalyzer.nl/batch>.
+        website <https://mutalyzer.nl/batch-jobs>.
 
         Batch jobs are processed using round-robin scheduling grouped by email
         address (or client IP address if no email address is specified). Per
@@ -167,7 +167,7 @@ class MutalyzerService(ServiceBase):
         Get the number of entries left for a batch job.
 
         Input and output file formats for batch jobs are explained on the
-        website <https://mutalyzer.nl/batch>.
+        website <https://mutalyzer.nl/batch-jobs>.
 
         @arg job_id: Batch job identifier.
 
@@ -181,7 +181,7 @@ class MutalyzerService(ServiceBase):
         Get the result of a batch job.
 
         Input and output file formats for batch jobs are explained on the
-        website <https://mutalyzer.nl/batch>.
+        website <https://mutalyzer.nl/batch-jobs>.
 
         On error an exception is raised:
           - detail: Human readable description of the error.
diff --git a/mutalyzer/sync.py b/mutalyzer/sync.py
index a1a1b7f90a3e687ef17aa833f3613b7895054d9c..e3ecc0c790413615084c6fc3dc2fe9cb16d47e48 100644
--- a/mutalyzer/sync.py
+++ b/mutalyzer/sync.py
@@ -156,8 +156,8 @@ class CacheSync(object):
 
         ::
 
-            >>> wsdl = 'http://mutalyzer.nl/mutalyzer/services/?wsdl'
-            >>> template = 'http://mutalyzer.nl/mutalyzer/Reference/{file}'
+            >>> wsdl = 'https://mutalyzer.nl/mutalyzer/services/?wsdl'
+            >>> template = 'https://mutalyzer.nl/mutalyzer/Reference/{file}'
             >>> self.sync_with_remote(wsdl, template)
             (14, 3)
 
diff --git a/mutalyzer/website/__init__.py b/mutalyzer/website/__init__.py
index 2ce0450bf8765e9197c37545aeef9b3281315c43..285cdd037c4a6286b433913da3b8188790be74ea 100644
--- a/mutalyzer/website/__init__.py
+++ b/mutalyzer/website/__init__.py
@@ -8,6 +8,7 @@ from __future__ import unicode_literals
 import logging
 import os
 import pkg_resources
+import urlparse
 
 from flask import Flask
 
@@ -46,3 +47,22 @@ def create_app():
         session.remove()
 
     return app
+
+
+def url_for(endpoint, **values):
+    """
+    Generates a URL to the given website endpoint.
+
+    Like :func:`Flask.url_for`, but for when you don't have an application or
+    request context.
+
+    Note that the generated URL will be based on the `WEBSITE_ROOT_URL`
+    configuration setting or `http://localhost` if not set.
+
+    :arg str endpoint: The endpoint of the URL (name of the function).
+    :arg str values: The variable arguments of the URL rule.
+    """
+    root = urlparse.urlsplit(settings.WEBSITE_ROOT_URL or 'http://localhost')
+    url_map = create_app().url_map.bind(root.netloc, root.path or '/',
+                                        url_scheme=root.scheme)
+    return url_map.build('website.%s' % endpoint, values, force_external=True)
diff --git a/mutalyzer/website/templates/static/js/generator.js b/mutalyzer/website/templates/static/js/generator.js
index b330c141c5a7e9fecfe0418efbf1d518d021cc1b..6bf57403407d13d733cb00fd8c16af600e877a4e 100644
--- a/mutalyzer/website/templates/static/js/generator.js
+++ b/mutalyzer/website/templates/static/js/generator.js
@@ -1,6 +1,6 @@
 /*
  * Mutalyzer Name Generator v0.1
- * http://www.mutalyzer.nl/
+ * https://www.mutalyzer.nl/
  * © 2010 LUMC
  */
 
diff --git a/mutalyzer/website/views.py b/mutalyzer/website/views.py
index df1fa71604a3f3a6f28351d75260d106077639a5..9fb3e4a39b11b882f20b15c89c3d96d2b0bbbfe5 100644
--- a/mutalyzer/website/views.py
+++ b/mutalyzer/website/views.py
@@ -937,15 +937,8 @@ def batch_jobs_submit():
             errors.append('Could not parse input file, please check your '
                           'file format.')
         else:
-            # Creates the result download URL from a job result_id.
-            def create_download_url(result_id):
-                return url_for('.batch_job_result',
-                               result_id=result_id,
-                               _external=True)
-
-            result_id = scheduler.addJob(
-                email, job, columns, job_type, argument=argument,
-                create_download_url=create_download_url)
+            result_id = scheduler.addJob(email, job, columns, job_type,
+                                         argument=argument)
 
             # Todo: We now assume that the job was not scheduled if there are
             #   messages, which is probably not correct.