diff --git a/.travis.yml b/.travis.yml
index 13e4e93fd7d32e6beb4ce7f33f0256e0a613f714..a3ce034131abcdc9c9ca6cf913e81fdbce7f2400 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,18 +15,31 @@ script:
   - SCITRAN_PERSISTENT_DB_PORT=27017 tests/bin/run-tests-ubuntu.sh
 
 after_success:
+  - if [ "$TRAVIS_EVENT_TYPE" == "push" -o "$TRAVIS_TAG" ]; then
+        SSH_KEY_FILE=$(mktemp -p $HOME/.ssh/);
+
+        openssl aes-256-cbc -K $encrypted_55750ae1fbc7_key -iv $encrypted_55750ae1fbc7_iv -in .github_deploy_key.enc -out "$SSH_KEY_FILE" -d;
+
+        chmod 600 "$SSH_KEY_FILE" && printf "%s\n" \
+              "Host github.com" \
+              "  IdentityFile $SSH_KEY_FILE" \
+              "  LogLevel ERROR" >> ~/.ssh/config;
+
+        git config --global user.email "travis@travis-ci.org";
+        git config --global user.name "Travis CI";
+        git config --global push.default simple;
+    fi
   - if [ "$TRAVIS_BRANCH" == "master" -o  "$TRAVIS_EVENT_TYPE" == "pull_request" ]; then
         bash <(curl -s https://codecov.io/bash) -cF python;
     fi
   - if [ "$TRAVIS_TAG" ]; then
         ./docker/build-trigger.sh Tag "$TRAVIS_TAG" "$BUILD_TRIGGER_URL";
+        ./bin/push-docs.sh "$GIT_REMOTE" tags "$TRAVIS_TAG" "Travis Core Docs Build - ${TRAVIS_BUILD_NUMBER}";
     fi
   - if [ "$TRAVIS_EVENT_TYPE" == "push" -a "$TRAVIS_BRANCH" == "master" ]; then
         ./docker/build-trigger.sh Branch "$TRAVIS_BRANCH" "$BUILD_TRIGGER_URL";
-        ./bin/build-docs.sh;
     fi
-    # Remove before pulling to master
-  - if [ "$TRAVIS_EVENT_TYPE" == "push" -a "$TRAVIS_BRANCH" == "swagger" ]; then
-        ./bin/build-docs.sh;
+  - if [ "$TRAVIS_EVENT_TYPE" == "push" -a -z "$TRAVIS_TAG" ]; then
+        ./bin/push-docs.sh "$GIT_REMOTE" branches "$TRAVIS_BRANCH" "Travis Core Docs Build - ${TRAVIS_BUILD_NUMBER}";
     fi
   
diff --git a/bin/build-docs.sh b/bin/build-docs.sh
deleted file mode 100755
index 7c70a20d7a772444f52889528bc69d0e0dc0d51c..0000000000000000000000000000000000000000
--- a/bin/build-docs.sh
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/usr/bin/env bash
-# This script will build the swagger documentation and push it to the gh-pages doc
-# For now this should only be run on the master branch
-
-set -eu
-
-unset CDPATH
-cd "$( dirname "${BASH_SOURCE[0]}" )/.."
-
-# Environment Variables:
-#  GIT_REMOTE: The full URL for the remote repo, including auth token
-#  TRAVIS_BUILD_NUMBER: The travis build number
-# Args:
-
-# Build documentation
-pushd swagger
-npm install
-npm run build
-popd
-
-# Decrypt SSH Key
-SSH_KEY_FILE=$(mktemp -u $HOME/.ssh/XXXXX)
-
-openssl aes-256-cbc -K $encrypted_55750ae1fbc7_key -iv $encrypted_55750ae1fbc7_iv -in .github_deploy_key.enc -out "$SSH_KEY_FILE" -d
-
-chmod 600 "$SSH_KEY_FILE" \
-	 && printf "%s\n" \
-		  "Host github.com" \
-		  "  IdentityFile $SSH_KEY_FILE" \
-		  "  LogLevel ERROR" >> ~/.ssh/config
-
-# Clone the gh-pages branch into a subdirectory (gh-pages)
-git clone ${GIT_REMOTE} --branch gh-pages --single-branch gh-pages
-
-# Copy documentation 
-cp -R swagger/build/swagger-ui/* gh-pages/
-
-pushd gh-pages
-# Check for changes
-if [[ `git status --porcelain` ]]; then
-	# Configure git
-	git config user.email "travis@travis-ci.org"
-	git config user.name "Travis CI"
-	git config --global push.default simple
-
-	# Add any modified files, and push
-	git add *
-	git commit --message "Travis Core Docs Build: ${TRAVIS_BUILD_NUMBER}"
-
-	# Push to remote repo
-	git push --quiet 
-fi
-popd
-
-# Cleanup subdirectory
-rm -rf gh-pages/
-
diff --git a/bin/push-docs.sh b/bin/push-docs.sh
new file mode 100755
index 0000000000000000000000000000000000000000..0b94d66323dcc17c674fcd87aee42abdbb36e575
--- /dev/null
+++ b/bin/push-docs.sh
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+# This script will build the swagger documentation and push it to the gh-pages doc
+# For now this should only be run on the master branch
+
+set -eu
+
+unset CDPATH
+cd "$( dirname "${BASH_SOURCE[0]}" )/.."
+
+# Environment Variables:
+# Args: <remote> (branches|tags) <branch_or_tag_name> <commit_message>
+#   remote: The git remote url
+#   branch_or_tag: Whether docs should go into the branches or tags subdirectory 
+#   branch_or_tag_name: The name of the tag or branch
+#   commit_message: The commit message
+
+main() {
+    if [ "$#" -ne 4 -o "$1" == "-h" ]; then
+        print_usage
+    fi
+
+    GIT_REMOTE=$1
+    DOCS_SUBDIR=$2
+    BRANCH_NAME=$3
+    COMMIT_MESSAGE=$4
+
+    # Determine version string
+    if [ "$DOCS_SUBDIR" == "branches" ]; then
+		COMMIT_REF="$(git rev-parse --short HEAD)"
+        DOC_VERSION="$BRANCH_NAME/$COMMIT_REF"
+    elif [ "$DOCS_SUBDIR" == "tags" ]; then
+        DOC_VERSION="$BRANCH_NAME"
+    else
+        print_usage
+    fi
+
+    # Build documentation
+	(
+    cd swagger
+    npm install
+    npm run build -- "--docs-version=$DOC_VERSION"
+	)
+
+    # Copy documentation 
+    if [ "$BRANCH_NAME" == "master" ]; then
+        checkin_master
+    else
+        checkin_branch "$DOCS_SUBDIR/$BRANCH_NAME"
+    fi
+
+    # Cleanup subdirectory
+    rm -rf gh-pages/
+}
+
+# Print usage and exit
+print_usage() {
+    echo "Usage: $0 <remote> Branch|Tag <branch_or_tag_name> <commit_message>"
+    exit 1
+}
+
+# Prune branches in a subdirectory of gh-pages
+# subdir: The subdirectory name (branches|tags)
+# remote_types: The remote type for ls-remote (head|tags)
+prune_branches() {
+    subdir=$1
+    remote_types=$2
+    if [ -d "gh-pages/${subdir}/" ]; then
+        (
+        cd gh-pages
+        for branch_dir in ${subdir}/*; do
+            branch_name="$(basename ${branch_dir})"
+            branch_exists="$(git ls-remote --${remote_types} ${GIT_REMOTE} ${branch_name} | wc -l)"
+            if [ "$branch_exists" -eq 0 ]; then
+                echo "Pruning branch: ${branch_name}"
+                git rm --quiet -rf "${branch_dir}"
+            fi
+        done
+        )
+    fi
+}
+
+# Checkin documentation for a single branche
+# target_dir: The destination directory (e.g. branches/<branch_name>)
+checkin_branch() {
+   target_dir=$1
+   # We try up to 3 times, sleeping for 3 or 7 seconds between attempts
+   for i in 3 7 100; do
+       # Allow capture of exit code of subshell
+       set +e
+        (
+        set -e
+
+        # Checkout gh-pages
+        rm -rf gh-pages/
+        git clone ${GIT_REMOTE} --branch gh-pages --single-branch gh-pages
+
+        # Create target directory and copy files
+        mkdir -p "gh-pages/${target_dir}"
+        cp -R swagger/build/swagger-ui/* "gh-pages/${target_dir}"
+
+        cd gh-pages
+	    if [ "$(git status --porcelain)" ]; then
+            # Add files
+            git add "${target_dir}*"
+
+            # Add any modified files, and push
+            git commit --message "$COMMIT_MESSAGE" 
+
+            # Push to remote repo
+            git push --quiet 
+        else
+            echo "No changes to commit"
+        fi
+        )
+        if [ "$?" -eq "0" ]; then
+            # Success case
+            break
+        elif [ "$i" -lt 100 ]; then
+            # Failure case, sleep and retry
+            echo "Error pushing branch docs, retrying in $i seconds."
+            sleep $i
+        else
+            # Final failure case
+            echo "Could not push branch docs, exiting"
+            exit 1
+        fi
+   done
+
+   set -e
+}
+
+# Prune non-existing branches and tags, and check-in master documentation, doing a force-push
+checkin_master() {
+    (
+    # Clone the gh-pages branch and prune any branches that don't exist in remotes
+    git clone ${GIT_REMOTE} --branch gh-pages --single-branch gh-pages
+    prune_branches branches heads
+    prune_branches tags tags
+
+    # Copy currently generated documentation into gh-pages
+    cp -R swagger/build/swagger-ui/* gh-pages/
+    cd gh-pages/
+
+	if [ "$(git status --porcelain)" ]; then
+        # Checkout a new orphan branch
+        git checkout --quiet --orphan gh-pages-new
+        # Add everything that still exists in this folder
+        git add *
+        # Commit
+        git commit --quiet --message "$COMMIT_MESSAGE"
+        # Force push to gh-pages 
+        git push --quiet --force --set-upstream origin gh-pages-new:gh-pages
+    else
+        echo "No changes to commit"
+    fi
+    )
+}
+
+main "$@"
+