diff --git a/docker-compose.yml b/docker-compose.yml
index 500a55a6fb21fed63c69840e7b65526def3ddadd..145696a4497ef93ae6d761550ae7a97a8c6b803a 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -122,6 +122,25 @@ services:
     logging:
       driver: json-file
 
+  fda-document-service:
+    restart: on-failure
+    container_name: fda-document-service
+    hostname: fda-document-service
+    build: ./fda-document-service
+    image: fda-document-service
+    networks:
+      fda-public:
+    environment:
+      SPRING_PROFILES_ACTIVE: docker
+      TZ: Europe/Vienna
+    ports:
+      - "9099:9099"
+    depends_on:
+      fda-discovery-service:
+        condition: service_healthy
+    logging:
+      driver: json-file
+
   fda-authentication-service:
     restart: on-failure
     container_name: fda-authentication-service
diff --git a/fda-document-service/.gitignore b/fda-document-service/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..cf45e2b44c0bdcd00a8a3e1640f092bc9f946db5
--- /dev/null
+++ b/fda-document-service/.gitignore
@@ -0,0 +1,37 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### Generated ###
+ready
+service_ready
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea/
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/fda-document-service/Dockerfile b/fda-document-service/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..93015fd61a17e46e5ebeb67da9f2004837dece9e
--- /dev/null
+++ b/fda-document-service/Dockerfile
@@ -0,0 +1,33 @@
+###### FIRST STAGE ######
+FROM fda-metadata-db:latest as dependency
+MAINTAINER Martin Weise <martin.weise@tuwien.ac.at>
+
+###### SECOND STAGE ######
+FROM maven:slim as build
+
+COPY ./pom.xml ./
+
+RUN mvn -fn -B dependency:go-offline > /dev/null
+
+COPY --from=dependency /root/.m2/repository/at/tuwien /root/.m2/repository/at/tuwien
+
+COPY ./rest-service ./rest-service
+COPY ./services ./services
+COPY ./report ./report
+
+# Make sure it compiles
+RUN mvn -q clean package -DskipTests > /dev/null
+
+###### THIRD STAGE ######
+FROM openjdk:11-jre-slim as runtime
+
+COPY ./service_ready /usr/bin
+RUN chmod +x /usr/bin/service_ready
+
+HEALTHCHECK --interval=10s --timeout=5s --retries=12 CMD service_ready
+
+COPY --from=build ./rest-service/target/rest-service-*.jar ./rest-service.jar
+
+EXPOSE 9099
+
+ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-jar", "./rest-service.jar"]
diff --git a/fda-document-service/README.md b/fda-document-service/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..afa0452aece523062f5fb095cb14409667ef2f74
--- /dev/null
+++ b/fda-document-service/README.md
@@ -0,0 +1,7 @@
+# FDA Document Service
+
+## Documentation
+
+- OpenAPI v3: http://localhost:9099/swagger-ui/index.html
+- OpenAPI v3 endpoint: http://localhost:9099/v3/api-docs/
+- OpenAPI v3 YAML: http://localhost:9099/v3/api-docs.yaml
\ No newline at end of file
diff --git a/fda-document-service/mvnw b/fda-document-service/mvnw
new file mode 100755
index 0000000000000000000000000000000000000000..a16b5431b4c3cab50323a3f558003fd0abd87dad
--- /dev/null
+++ b/fda-document-service/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+#   JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+#   M2_HOME - location of maven2's installed home dir
+#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
+#     e.g. to debug Maven itself, use
+#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+  if [ -f /etc/mavenrc ] ; then
+    . /etc/mavenrc
+  fi
+
+  if [ -f "$HOME/.mavenrc" ] ; then
+    . "$HOME/.mavenrc"
+  fi
+
+fi
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+  CYGWIN*) cygwin=true ;;
+  MINGW*) mingw=true;;
+  Darwin*) darwin=true
+    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+    if [ -z "$JAVA_HOME" ]; then
+      if [ -x "/usr/libexec/java_home" ]; then
+        export JAVA_HOME="`/usr/libexec/java_home`"
+      else
+        export JAVA_HOME="/Library/Java/Home"
+      fi
+    fi
+    ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+  if [ -r /etc/gentoo-release ] ; then
+    JAVA_HOME=`java-config --jre-home`
+  fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+  ## resolve links - $0 may be a link to maven's home
+  PRG="$0"
+
+  # need this for relative symlinks
+  while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+      PRG="$link"
+    else
+      PRG="`dirname "$PRG"`/$link"
+    fi
+  done
+
+  saveddir=`pwd`
+
+  M2_HOME=`dirname "$PRG"`/..
+
+  # make it fully qualified
+  M2_HOME=`cd "$M2_HOME" && pwd`
+
+  cd "$saveddir"
+  # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=`cygpath --unix "$M2_HOME"`
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME="`(cd "$M2_HOME"; pwd)`"
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+  javaExecutable="`which javac`"
+  if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+    # readlink(1) is not available as standard on Solaris 10.
+    readLink=`which readlink`
+    if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+      if $darwin ; then
+        javaHome="`dirname \"$javaExecutable\"`"
+        javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+      else
+        javaExecutable="`readlink -f \"$javaExecutable\"`"
+      fi
+      javaHome="`dirname \"$javaExecutable\"`"
+      javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+      JAVA_HOME="$javaHome"
+      export JAVA_HOME
+    fi
+  fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+  if [ -n "$JAVA_HOME"  ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+    fi
+  else
+    JAVACMD="`which java`"
+  fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+  echo "Error: JAVA_HOME is not defined correctly." >&2
+  echo "  We cannot execute $JAVACMD" >&2
+  exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+  echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+  if [ -z "$1" ]
+  then
+    echo "Path not specified to find_maven_basedir"
+    return 1
+  fi
+
+  basedir="$1"
+  wdir="$1"
+  while [ "$wdir" != '/' ] ; do
+    if [ -d "$wdir"/.mvn ] ; then
+      basedir=$wdir
+      break
+    fi
+    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+    if [ -d "${wdir}" ]; then
+      wdir=`cd "$wdir/.."; pwd`
+    fi
+    # end of workaround
+  done
+  echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+  if [ -f "$1" ]; then
+    echo "$(tr -s '\n' ' ' < "$1")"
+  fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+  exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Found .mvn/wrapper/maven-wrapper.jar"
+    fi
+else
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+    fi
+    if [ -n "$MVNW_REPOURL" ]; then
+      jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+    else
+      jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+    fi
+    while IFS="=" read key value; do
+      case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+      esac
+    done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Downloading from: $jarUrl"
+    fi
+    wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+    if $cygwin; then
+      wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+    fi
+
+    if command -v wget > /dev/null; then
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Found wget ... using wget"
+        fi
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            wget "$jarUrl" -O "$wrapperJarPath"
+        else
+            wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+        fi
+    elif command -v curl > /dev/null; then
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Found curl ... using curl"
+        fi
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            curl -o "$wrapperJarPath" "$jarUrl" -f
+        else
+            curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+        fi
+
+    else
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Falling back to using Java to download"
+        fi
+        javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+        # For Cygwin, switch paths to Windows format before running javac
+        if $cygwin; then
+          javaClass=`cygpath --path --windows "$javaClass"`
+        fi
+        if [ -e "$javaClass" ]; then
+            if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+                if [ "$MVNW_VERBOSE" = true ]; then
+                  echo " - Compiling MavenWrapperDownloader.java ..."
+                fi
+                # Compiling the Java class
+                ("$JAVA_HOME/bin/javac" "$javaClass")
+            fi
+            if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+                # Running the downloader
+                if [ "$MVNW_VERBOSE" = true ]; then
+                  echo " - Running MavenWrapperDownloader.java ..."
+                fi
+                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+            fi
+        fi
+    fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+  echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=`cygpath --path --windows "$M2_HOME"`
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+    MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+  $MAVEN_OPTS \
+  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+  "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/fda-document-service/mvnw.cmd b/fda-document-service/mvnw.cmd
new file mode 100644
index 0000000000000000000000000000000000000000..c8d43372c986d97911cdc21bd87e0cbe3d83bdda
--- /dev/null
+++ b/fda-document-service/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements.  See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership.  The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License.  You may obtain a copy of the License at
+@REM
+@REM    https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied.  See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM     e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+    IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Found %WRAPPER_JAR%
+    )
+) else (
+    if not "%MVNW_REPOURL%" == "" (
+        SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+    )
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Couldn't find %WRAPPER_JAR%, downloading it ...
+        echo Downloading from: %DOWNLOAD_URL%
+    )
+
+    powershell -Command "&{"^
+		"$webclient = new-object System.Net.WebClient;"^
+		"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+		"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+		"}"^
+		"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+		"}"
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Finished downloading %WRAPPER_JAR%
+    )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/fda-document-service/pom.xml b/fda-document-service/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c53a944f5803686f4cea695623aa1655eb00c23c
--- /dev/null
+++ b/fda-document-service/pom.xml
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.3.10.RELEASE</version>
+    </parent>
+
+    <groupId>at.tuwien</groupId>
+    <artifactId>fda-document-service</artifactId>
+    <version>1.1.0-alpha</version>
+    <name>fda-document-service</name>
+    <description>Demo project for Spring Boot</description>
+
+    <packaging>pom</packaging>
+    <modules>
+        <module>rest-service</module>
+        <module>services</module>
+        <module>report</module>
+    </modules>
+
+    <properties>
+        <java.version>11</java.version>
+        <spring-cloud.version>3.0.1</spring-cloud.version>
+        <mapstruct.version>1.4.2.Final</mapstruct.version>
+        <docker.version>3.2.7</docker.version>
+        <testcontainers.version>1.15.2</testcontainers.version>
+        <swagger.version>2.1.7</swagger.version>
+        <jacoco.version>0.8.7</jacoco.version>
+        <sqlserver.version>9.2.1.jre11</sqlserver.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-webflux</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency><!-- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes#validation-starter-no-longer-included-in-web-starters -->
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-bootstrap</artifactId>
+            <version>${spring-cloud.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <!-- Data Source -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-elasticsearch</artifactId>
+        </dependency>
+        <!-- Entity and API -->
+        <dependency>
+            <groupId>at.tuwien</groupId>
+            <artifactId>fda-metadata-db-api</artifactId>
+            <version>${project.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>at.tuwien</groupId>
+            <artifactId>fda-metadata-db-entites</artifactId>
+            <version>${project.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <!-- DataSource -->
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+            <version>${postgresql.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.mariadb.jdbc</groupId>
+            <artifactId>mariadb-java-client</artifactId>
+            <version>${mariadb.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>${mysql.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.microsoft.sqlserver</groupId>
+            <artifactId>mssql-jdbc</artifactId>
+            <version>${sqlserver.version}</version>
+        </dependency>
+        <!-- Testing -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.junit.jupiter</groupId>
+                    <artifactId>junit-vintage-engine</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jacoco</groupId>
+            <artifactId>jacoco-maven-plugin</artifactId>
+            <version>${jacoco.version}</version>
+        </dependency>
+        <!-- IDE -->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+        <!-- Docker -->
+        <dependency>
+            <groupId>com.github.docker-java</groupId>
+            <artifactId>docker-java</artifactId>
+            <version>${docker.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>javax.ws.rs</groupId>
+                    <artifactId>jsr311-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.github.docker-java</groupId>
+            <artifactId>docker-java-transport-httpclient5</artifactId>
+            <version>${docker.version}</version>
+        </dependency>
+        <!-- Mapping -->
+        <dependency>
+            <groupId>org.mapstruct</groupId>
+            <artifactId>mapstruct-processor</artifactId>
+            <version>${mapstruct.version}</version>
+            <optional>true</optional><!-- IntelliJ -->
+        </dependency>
+        <dependency>
+            <groupId>org.mapstruct</groupId>
+            <artifactId>mapstruct</artifactId>
+            <version>${mapstruct.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>${basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/application*.yml</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <version>${jacoco.version}</version>
+                <configuration>
+                    <excludes>
+                        <exclude>at/tuwien/utils/**/*</exclude>
+                        <exclude>at/tuwien/handlers/**/*</exclude>
+                        <exclude>at/tuwien/seeder/**/*</exclude>
+                        <exclude>at/tuwien/mapper/**/*</exclude>
+                        <exclude>at/tuwien/exception/**/*</exclude>
+                        <exclude>at/tuwien/config/**/*</exclude>
+                        <exclude>**/FdaContainerManagingApplication.class</exclude>
+                    </excludes>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>default-prepare-agent</id>
+                        <goals>
+                            <goal>prepare-agent</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>report</id>
+                        <phase>verify</phase>
+                        <goals>
+                            <goal>report</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/fda-document-service/report/pom.xml b/fda-document-service/report/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a2aa61fbb830c24d05265bdb3e75de0f058cee40
--- /dev/null
+++ b/fda-document-service/report/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>at.tuwien</groupId>
+        <artifactId>fda-document-service</artifactId>
+        <version>1.1.0-alpha</version>
+    </parent>
+
+    <artifactId>report</artifactId>
+    <version>1.1.0-alpha</version>
+    <name>fda-document-service-report</name>
+    <description>
+        This module is only intended for the pipeline coverage report. See the detailed report in the
+        respective modules
+    </description>
+
+    <properties>
+        <jacoco.version>0.8.7</jacoco.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>at.tuwien</groupId>
+            <artifactId>rest-service</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>at.tuwien</groupId>
+            <artifactId>services</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <version>${jacoco.version}</version>
+                <executions>
+                    <execution>
+                        <id>report-aggregate</id>
+                        <phase>verify</phase>
+                        <goals>
+                            <goal>report-aggregate</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/fda-document-service/rest-service/pom.xml b/fda-document-service/rest-service/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bd42b4e61d672a739038fce699fb8f7ba6e09992
--- /dev/null
+++ b/fda-document-service/rest-service/pom.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>at.tuwien</groupId>
+        <artifactId>fda-document-service</artifactId>
+        <version>1.1.0-alpha</version>
+    </parent>
+
+    <artifactId>rest-service</artifactId>
+    <version>1.1.0-alpha</version>
+    <name>fda-document-service-rest-service</name>
+
+    <properties>
+        <jacoco.version>0.8.7</jacoco.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>at.tuwien</groupId>
+            <artifactId>services</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal><!-- to make it exuteable with $ java -jar ./app.jar -->
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/fda-document-service/rest-service/src/main/java/at/tuwien/FdaDocumentManagingApplication.java b/fda-document-service/rest-service/src/main/java/at/tuwien/FdaDocumentManagingApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..582259d7d3685b4954e8f70263e0ed66b83e5a98
--- /dev/null
+++ b/fda-document-service/rest-service/src/main/java/at/tuwien/FdaDocumentManagingApplication.java
@@ -0,0 +1,23 @@
+package at.tuwien;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+@SpringBootApplication
+@EnableJpaAuditing
+@EnableTransactionManagement
+@EnableElasticsearchRepositories(basePackages = {"at.tuwien.repository.elastic"})
+@EnableJpaRepositories(basePackages = {"at.tuwien.repository.jpa"})
+@EntityScan(basePackages = {"at.tuwien.entities"})
+public class FdaDocumentManagingApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(FdaDocumentManagingApplication.class, args);
+    }
+
+}
diff --git a/fda-document-service/rest-service/src/main/java/at/tuwien/config/SwaggerConfig.java b/fda-document-service/rest-service/src/main/java/at/tuwien/config/SwaggerConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..3bdf7daf401e7ff161b3a1ea43db70ad74f601e9
--- /dev/null
+++ b/fda-document-service/rest-service/src/main/java/at/tuwien/config/SwaggerConfig.java
@@ -0,0 +1,48 @@
+package at.tuwien.config;
+
+import io.swagger.v3.oas.models.ExternalDocumentation;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Contact;
+import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.info.License;
+import org.springdoc.core.GroupedOpenApi;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.info.BuildProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+
+@Configuration
+public class SwaggerConfig {
+
+    @Value("${app.version:unknown}")
+    private String version;
+
+    @Bean
+    public OpenAPI springShopOpenAPI() {
+        return new OpenAPI()
+                .info(new Info()
+                        .title("Database Repository Document Service API")
+                        .contact(new Contact()
+                                .name("Prof. Andreas Rauber")
+                                .email("andreas.rauber@tuwien.ac.at"))
+                        .description("Service that manages the documents")
+                        .version(version)
+                        .license(new License()
+                                .name("Apache 2.0")
+                                .url("https://www.apache.org/licenses/LICENSE-2.0")))
+                .externalDocs(new ExternalDocumentation()
+                        .description("Wiki Documentation")
+                        .url("https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/wikis"));
+    }
+
+    @Bean
+    public GroupedOpenApi publicApi() {
+        return GroupedOpenApi.builder()
+                .group("document-service")
+                .pathsToMatch("/api/**")
+                .build();
+    }
+
+}
diff --git a/fda-document-service/rest-service/src/main/java/at/tuwien/endpoints/DocumentEndpoint.java b/fda-document-service/rest-service/src/main/java/at/tuwien/endpoints/DocumentEndpoint.java
new file mode 100644
index 0000000000000000000000000000000000000000..2436b9748bc4e11979c02f8f947e99e481da8287
--- /dev/null
+++ b/fda-document-service/rest-service/src/main/java/at/tuwien/endpoints/DocumentEndpoint.java
@@ -0,0 +1,71 @@
+package at.tuwien.endpoints;
+
+import at.tuwien.api.document.record.CreateDraftDto;
+import at.tuwien.api.document.record.DraftDto;
+import at.tuwien.exception.DraftRecordCreateException;
+import at.tuwien.service.DocumentService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import java.security.Principal;
+
+
+@Log4j2
+@RestController
+@CrossOrigin(origins = "*")
+@ControllerAdvice
+@RequestMapping("/api/document")
+public class DocumentEndpoint {
+
+    private final DocumentService documentService;
+
+    @Autowired
+    public DocumentEndpoint(DocumentService documentService) {
+        this.documentService = documentService;
+    }
+
+    @PostMapping
+    @PreAuthorize("hasRole('ROLE_RESEARCHER')")
+    @Transactional(readOnly = true)
+    @Operation(summary = "Create a draft", security = @SecurityRequirement(name = "bearerAuth"))
+    public ResponseEntity<DraftDto> create(@NotNull @Valid @RequestBody CreateDraftDto data,
+                                           @NotNull Principal principal) throws DraftRecordCreateException {
+        final DraftDto document = documentService.create(data, principal);
+        return ResponseEntity.status(HttpStatus.CREATED)
+                .body(document);
+    }
+
+    @GetMapping("/{id}")
+    @PreAuthorize("hasRole('ROLE_RESEARCHER')")
+    @Transactional(readOnly = true)
+    @Operation(summary = "Find a draft", security = @SecurityRequirement(name = "bearerAuth"))
+    public ResponseEntity<DraftDto> find(@NotNull @PathVariable("id") String documentId,
+                                         @NotNull Principal principal) throws DraftRecordCreateException {
+        final DraftDto document = documentService.findById(documentId, principal);
+        log.info("Found draft record with id {}", documentId);
+        log.debug("found draft record {}", document);
+        return ResponseEntity.status(HttpStatus.OK)
+                .body(document);
+    }
+
+    @PostMapping("/{id}")
+    @PreAuthorize("hasRole('ROLE_RESEARCHER')")
+    @Transactional(readOnly = true)
+    @Operation(summary = "Reserve draft DOI", security = @SecurityRequirement(name = "bearerAuth"))
+    public ResponseEntity<DraftDto> reserve(@NotNull @PathVariable("id") String documentId,
+                                            @NotNull Principal principal) throws DraftRecordCreateException {
+        final DraftDto document = documentService.reserveDoi(documentId, principal);
+        return ResponseEntity.status(HttpStatus.CREATED)
+                .body(document);
+    }
+
+}
diff --git a/fda-document-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java b/fda-document-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..8941436966d303f9360cda96ecfa94e59c17c942
--- /dev/null
+++ b/fda-document-service/rest-service/src/main/java/at/tuwien/handlers/ApiExceptionHandler.java
@@ -0,0 +1,28 @@
+package at.tuwien.handlers;
+
+import at.tuwien.api.error.ApiErrorDto;
+import at.tuwien.exception.*;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.context.request.WebRequest;
+import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
+
+@ControllerAdvice
+public class ApiExceptionHandler extends ResponseEntityExceptionHandler {
+
+    @ResponseStatus(HttpStatus.EXPECTATION_FAILED)
+    @ExceptionHandler(DraftRecordCreateException.class)
+    public ResponseEntity<ApiErrorDto> handle(DraftRecordCreateException e, WebRequest request) {
+        final ApiErrorDto response = ApiErrorDto.builder()
+                .status(HttpStatus.EXPECTATION_FAILED)
+                .message(e.getLocalizedMessage())
+                .code("error.document.create")
+                .build();
+        return new ResponseEntity<>(response, new HttpHeaders(), response.getStatus());
+    }
+
+}
\ No newline at end of file
diff --git a/fda-document-service/rest-service/src/main/resources/application-docker.yml b/fda-document-service/rest-service/src/main/resources/application-docker.yml
new file mode 100644
index 0000000000000000000000000000000000000000..46f56dc08b4dff9989e3e1d942e2253678759f7a
--- /dev/null
+++ b/fda-document-service/rest-service/src/main/resources/application-docker.yml
@@ -0,0 +1,34 @@
+app.version: '@project.version@'
+spring:
+  main.banner-mode: off
+  datasource:
+    url: jdbc:postgresql://fda-metadata-db:5432/fda
+    driver-class-name: org.postgresql.Driver
+    username: postgres
+    password: postgres
+  jpa:
+    show-sql: false
+    database-platform: org.hibernate.dialect.PostgreSQLDialect
+    hibernate:
+      ddl-auto: validate
+    open-in-view: false
+  application:
+    name: fda-document-service
+  cloud:
+    loadbalancer.ribbon.enabled: false
+server.port: 9099
+logging:
+  pattern.console: "%d %highlight(%-5level) %msg%n"
+  level:
+    root: warn
+    at.tuwien.: debug
+    at.tuwien.gateway.: trace
+    org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug
+eureka:
+  instance.hostname: fda-document-service
+  client.serviceUrl.defaultZone: http://fda-discovery-service:9090/eureka/
+fda:
+  mount.path: /tmp
+  ready.path: /ready
+  document.endpoint: https://test.researchdata.tuwien.ac.at
+dev.token: "${TOKEN}"
\ No newline at end of file
diff --git a/fda-document-service/rest-service/src/main/resources/application.yml b/fda-document-service/rest-service/src/main/resources/application.yml
new file mode 100644
index 0000000000000000000000000000000000000000..47db505983d03a94640962f3b394da6c91bd3ac7
--- /dev/null
+++ b/fda-document-service/rest-service/src/main/resources/application.yml
@@ -0,0 +1,35 @@
+app.version: '@project.version@'
+spring:
+  main.banner-mode: off
+  datasource:
+    url: jdbc:postgresql://localhost:5432/fda
+    driver-class-name: org.postgresql.Driver
+    username: postgres
+    password: postgres
+  jpa:
+    show-sql: false
+    database-platform: org.hibernate.dialect.PostgreSQLDialect
+    hibernate:
+      ddl-auto: validate
+    open-in-view: false
+  application:
+    name: fda-document-service
+  cloud:
+    loadbalancer.ribbon.enabled: false
+springdoc.swagger-ui.enabled: true
+server.port: 9099
+logging:
+  pattern.console: "%d %highlight(%-5level) %msg%n"
+  level:
+    root: warn
+    at.tuwien.: debug
+    at.tuwien.gateway.: trace
+    org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug
+eureka:
+  instance.hostname: fda-document-service
+  client.serviceUrl.defaultZone: http://localhost:9090/eureka/
+fda:
+  mount.path: /tmp
+  ready.path: ./ready
+  document.endpoint: https://test.researchdata.tuwien.ac.at
+dev.token: "${TOKEN}"
\ No newline at end of file
diff --git a/fda-document-service/rest-service/src/main/resources/config.properties b/fda-document-service/rest-service/src/main/resources/config.properties
new file mode 100644
index 0000000000000000000000000000000000000000..e993ed9c62272ab86ae23a64f6195f21e465216f
--- /dev/null
+++ b/fda-document-service/rest-service/src/main/resources/config.properties
@@ -0,0 +1 @@
+# https://github.com/Netflix/Hystrix/issues/275
\ No newline at end of file
diff --git a/fda-document-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java b/fda-document-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f4f0cc7ebc0635d6e11bbccd62c25dbae8dd6da
--- /dev/null
+++ b/fda-document-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java
@@ -0,0 +1,81 @@
+package at.tuwien;
+
+import at.tuwien.api.document.metadata.*;
+import at.tuwien.api.document.record.*;
+import org.springframework.test.context.TestPropertySource;
+
+import java.time.Instant;
+import java.util.Date;
+import java.util.List;
+
+@TestPropertySource(locations = "classpath:application.properties")
+public abstract class BaseUnitTest {
+
+    public final static String USER_1_USERNAME = "junit";
+
+    public final static AccessTypeDto DOCUMENT_1_RECORD_TYPE = AccessTypeDto.PUBLIC;
+    public final static FileTypeDto DOCUMENT_1_FILE_TYPE = FileTypeDto.PUBLIC;
+
+    public final static AccessOptionsDto DOCUMENT_1_ACCESS_OPTIONS = AccessOptionsDto.builder()
+            .record(DOCUMENT_1_RECORD_TYPE)
+            .files(DOCUMENT_1_FILE_TYPE)
+            .build();
+
+    public final static Boolean DOCUMENT_1_FILES_ENABLED = true;
+
+    public final static FilesOptionsDto DOCUMENT_1_FILES_OPTIONS = FilesOptionsDto.builder()
+            .enabled(DOCUMENT_1_FILES_ENABLED)
+            .build();
+
+    public final static String DOCUMENT_1_TITLE = "Test Draft";
+    public final static String DOCUMENT_1_RESOURCE_TYPE_TYPE = "other";
+    public final static Date DOCUMENT_1_PUBLICATION_DATE = Date.from(Instant.now());
+
+    public final static ResourceTypeDto DOCUMENT_1_RESOURCE_TYPE = ResourceTypeDto.builder()
+            .id(DOCUMENT_1_RESOURCE_TYPE_TYPE)
+            .build();
+
+    public final static String IDENTIFIER_1_IDENTIFIER = "0000-0003-4216-302X";
+    public final static IdentifierTypeDto IDENTIFIER_1_TYPE = IdentifierTypeDto.ORCID;
+
+    public final static IdentifierDto IDENTIFIER_1 = IdentifierDto.builder()
+            .identifier(IDENTIFIER_1_IDENTIFIER)
+            .scheme(IDENTIFIER_1_TYPE)
+            .build();
+
+    public final static String PERSON_1_GIVEN_NAME = "Martin";
+    public final static String PERSON_1_FAMILY_NAME = "Weise";
+    public final static String PERSON_1_NAME = "Weise, Martin";
+    public final static PersonOrOrgTypeDto PERSON_1_TYPE = PersonOrOrgTypeDto.PERSONAL;
+
+    public final static PersonOrOrganizationDto PERSON_1 = PersonOrOrganizationDto.builder()
+            .givenName(PERSON_1_GIVEN_NAME)
+            .familyName(PERSON_1_FAMILY_NAME)
+            .name(PERSON_1_NAME)
+            .type(PERSON_1_TYPE)
+            .identifiers(List.of(IDENTIFIER_1))
+            .build();
+
+    public final static AffiliationDto AFFILIATION_1 = AffiliationDto.builder()
+            .name("TU Wien")
+            .build();
+
+    public final static CreatorDto CREATOR_1 = CreatorDto.builder()
+            .personOrOrganization(PERSON_1)
+            .affiliations(List.of(AFFILIATION_1))
+            .build();
+
+    public final static MetadataDto DOCUMENT_1_METADATA = MetadataDto.builder()
+            .title(DOCUMENT_1_TITLE)
+            .resourceType(DOCUMENT_1_RESOURCE_TYPE)
+            .publicationDate(DOCUMENT_1_PUBLICATION_DATE)
+            .creators(List.of(CREATOR_1))
+            .build();
+
+    public final static CreateDraftDto DOCUMENT_1_CREATE_DRAFT = CreateDraftDto.builder()
+            .access(DOCUMENT_1_ACCESS_OPTIONS)
+            .files(DOCUMENT_1_FILES_OPTIONS)
+            .metadata(DOCUMENT_1_METADATA)
+            .build();
+
+}
diff --git a/fda-document-service/rest-service/src/test/java/at/tuwien/endpoint/DocumentEndpointUnitTest.java b/fda-document-service/rest-service/src/test/java/at/tuwien/endpoint/DocumentEndpointUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0965a30b1e3fe46573e7e50f798b044d9af81cc4
--- /dev/null
+++ b/fda-document-service/rest-service/src/test/java/at/tuwien/endpoint/DocumentEndpointUnitTest.java
@@ -0,0 +1,13 @@
+package at.tuwien.endpoint;
+
+import at.tuwien.BaseUnitTest;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+@ExtendWith(SpringExtension.class)
+@SpringBootTest
+public class DocumentEndpointUnitTest extends BaseUnitTest {
+
+
+}
diff --git a/fda-document-service/rest-service/src/test/java/at/tuwien/service/DocumentEndpointIntegrationTest.java b/fda-document-service/rest-service/src/test/java/at/tuwien/service/DocumentEndpointIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..e62b5d378c6e62952fd88929cf7e43bd169fb062
--- /dev/null
+++ b/fda-document-service/rest-service/src/test/java/at/tuwien/service/DocumentEndpointIntegrationTest.java
@@ -0,0 +1,55 @@
+package at.tuwien.service;
+
+import at.tuwien.BaseUnitTest;
+import at.tuwien.api.document.record.CreateDraftDto;
+import at.tuwien.api.document.record.DraftDto;
+import at.tuwien.exception.DraftRecordCreateException;
+import lombok.extern.log4j.Log4j2;
+import org.apache.http.auth.BasicUserPrincipal;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import java.security.Principal;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+@Log4j2
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
+@ExtendWith(SpringExtension.class)
+@SpringBootTest
+public class DocumentEndpointIntegrationTest extends BaseUnitTest {
+
+    @Autowired
+    private DocumentService documentService;
+
+    @Test
+    public void create_succeeds() throws DraftRecordCreateException {
+        final CreateDraftDto request = DOCUMENT_1_CREATE_DRAFT;
+        final Principal principal = new BasicUserPrincipal(USER_1_USERNAME);
+
+        /* mock */
+
+        /* test */
+        final DraftDto response = documentService.create(request, principal);
+        assertEquals(DOCUMENT_1_TITLE, response.getMetadata().getTitle());
+    }
+
+    @Test
+    public void reserve_succeeds() throws DraftRecordCreateException {
+        final CreateDraftDto request = DOCUMENT_1_CREATE_DRAFT;
+        final Principal principal = new BasicUserPrincipal(USER_1_USERNAME);
+
+        /* mock */
+
+        /* test */
+        final DraftDto document = documentService.create(request, principal);
+        final DraftDto response = documentService.reserveDoi(document.getId(), principal);
+        assertNotNull(response.getPids().getDoi());
+    }
+
+}
diff --git a/fda-document-service/rest-service/src/test/resources/application.properties b/fda-document-service/rest-service/src/test/resources/application.properties
new file mode 100644
index 0000000000000000000000000000000000000000..1f8a9f4089f393b2a8d25f28472a80a35658aab5
--- /dev/null
+++ b/fda-document-service/rest-service/src/test/resources/application.properties
@@ -0,0 +1,15 @@
+# disable discovery
+spring.cloud.discovery.enabled = false
+
+# disable cloud config and config discovery
+spring.cloud.config.discovery.enabled = false
+spring.cloud.config.enabled = false
+
+# disable datasource
+spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
+spring.datasource.driverClassName=org.h2.Driver
+spring.datasource.username=sa
+spring.datasource.password=password
+spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
+spring.jpa.hibernate.ddl-auto=create-drop
+spring.jpa.show-sql=false
\ No newline at end of file
diff --git a/fda-document-service/services/pom.xml b/fda-document-service/services/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..556e2833e894c562c2186e885368323d805142dd
--- /dev/null
+++ b/fda-document-service/services/pom.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>fda-document-service</artifactId>
+        <groupId>at.tuwien</groupId>
+        <version>1.1.0-alpha</version>
+    </parent>
+
+    <artifactId>services</artifactId>
+    <version>1.1.0-alpha</version>
+    <name>fda-document-service-services</name>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${java.version}</source>
+                    <target>${java.version}</target>
+                    <annotationProcessorPaths>
+                        <path>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                            <version>${lombok.version}</version>
+                        </path>
+                        <!-- keep this order https://stackoverflow.com/questions/47676369/mapstruct-and-lombok-not-working-together#answer-65021876 -->
+                        <path>
+                            <groupId>org.mapstruct</groupId>
+                            <artifactId>mapstruct-processor</artifactId>
+                            <version>${mapstruct.version}</version>
+                        </path>
+                    </annotationProcessorPaths>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/fda-document-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java b/fda-document-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..e33f0dba4dddf90216af08dbb5ec98b184fbf6f6
--- /dev/null
+++ b/fda-document-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java
@@ -0,0 +1,58 @@
+package at.tuwien.auth;
+
+import at.tuwien.gateway.AuthenticationServiceGateway;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Slf4j
+public class AuthTokenFilter extends OncePerRequestFilter {
+
+    private final AuthenticationServiceGateway authenticationServiceGateway;
+
+    public AuthTokenFilter(AuthenticationServiceGateway authenticationServiceGateway) {
+        this.authenticationServiceGateway = authenticationServiceGateway;
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+            throws ServletException, IOException {
+        final String jwt = parseJwt(request);
+        if (jwt != null) {
+            final UserDetails userDetails = authenticationServiceGateway.validate(jwt);
+            log.info("Authenticated user with username {} and authorities {}", userDetails.getUsername(),
+                    userDetails.getAuthorities());
+            log.debug("authenticated user {}", userDetails);
+            final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
+                    userDetails, null, userDetails.getAuthorities());
+            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+
+            SecurityContextHolder.getContext().setAuthentication(authentication);
+        }
+        filterChain.doFilter(request, response);
+    }
+
+    /**
+     * Parses the token from the HTTP header of the request
+     *
+     * @param request The request.
+     * @return The token.
+     */
+    private String parseJwt(HttpServletRequest request) {
+        String headerAuth = request.getHeader("Authorization");
+        if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
+            return headerAuth.substring(7, headerAuth.length());
+        }
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/fda-document-service/services/src/main/java/at/tuwien/config/GatewayConfig.java b/fda-document-service/services/src/main/java/at/tuwien/config/GatewayConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..006541ad8cd45351c455e1bf03b4c546acf3a6e8
--- /dev/null
+++ b/fda-document-service/services/src/main/java/at/tuwien/config/GatewayConfig.java
@@ -0,0 +1,22 @@
+package at.tuwien.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.DefaultUriBuilderFactory;
+
+@Configuration
+public class GatewayConfig {
+
+    @Value("${fda.document.endpoint}")
+    private String documentEndpoint;
+
+    @Bean
+    public RestTemplate restTemplate() {
+        final RestTemplate restTemplate =  new RestTemplate();
+        restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(documentEndpoint));
+        return restTemplate;
+    }
+
+}
diff --git a/fda-document-service/services/src/main/java/at/tuwien/config/InvenioConfig.java b/fda-document-service/services/src/main/java/at/tuwien/config/InvenioConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..98aa6731f87e383a472acfc579f08b819e1e0dc1
--- /dev/null
+++ b/fda-document-service/services/src/main/java/at/tuwien/config/InvenioConfig.java
@@ -0,0 +1,15 @@
+package at.tuwien.config;
+
+import lombok.Getter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+
+@Getter
+@Configuration
+public class InvenioConfig {
+
+    @Value("${dev.token}")
+    private String debugToken;
+
+}
diff --git a/fda-document-service/services/src/main/java/at/tuwien/config/ReadyConfig.java b/fda-document-service/services/src/main/java/at/tuwien/config/ReadyConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..2250fa50884df3f47b0b063975aea74f06203f80
--- /dev/null
+++ b/fda-document-service/services/src/main/java/at/tuwien/config/ReadyConfig.java
@@ -0,0 +1,25 @@
+package at.tuwien.config;
+
+import com.google.common.io.Files;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.event.EventListener;
+
+import java.io.File;
+import java.io.IOException;
+
+@Log4j2
+@Configuration
+public class ReadyConfig {
+
+    @Value("${fda.ready.path}")
+    private String readyPath;
+
+    @EventListener(ApplicationReadyEvent.class)
+    public void init() throws IOException {
+        Files.touch(new File(readyPath));
+    }
+
+}
diff --git a/fda-document-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java b/fda-document-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..70dac68fcd138939eaa08a33a7789bd5830b369d
--- /dev/null
+++ b/fda-document-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java
@@ -0,0 +1,93 @@
+package at.tuwien.config;
+
+import at.tuwien.auth.AuthTokenFilter;
+import at.tuwien.gateway.AuthenticationServiceGateway;
+import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
+import io.swagger.v3.oas.annotations.security.SecurityScheme;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+import javax.servlet.http.HttpServletResponse;
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+@SecurityScheme(
+        name = "bearerAuth",
+        type = SecuritySchemeType.HTTP,
+        bearerFormat = "JWT",
+        scheme = "bearer"
+)
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+    private final AuthenticationServiceGateway authenticationServiceGateway;
+
+    @Autowired
+    public WebSecurityConfig(AuthenticationServiceGateway authenticationServiceGateway) {
+        this.authenticationServiceGateway = authenticationServiceGateway;
+    }
+
+    @Bean
+    public AuthTokenFilter authTokenFilter() {
+        return new AuthTokenFilter(authenticationServiceGateway);
+    }
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        /* enable CORS and disable CSRF */
+        http = http.cors().and().csrf().disable();
+        /* set session management to stateless */
+        http = http
+                .sessionManagement()
+                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+                .and();
+        /* set unauthorized requests exception handler */
+        http = http
+                .exceptionHandling()
+                .authenticationEntryPoint(
+                        (request, response, ex) -> {
+                            response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
+                                    ex.getMessage()
+                            );
+                        }
+                ).and();
+        /* set permissions on endpoints */
+        http.authorizeRequests()
+                /* our public endpoints */
+                .antMatchers(HttpMethod.GET, "/api/document/**").permitAll()
+                .antMatchers("/v3/api-docs.yaml",
+                        "/v3/api-docs/**",
+                        "/swagger-ui/**",
+                        "/swagger-ui.html").permitAll()
+                /* our private endpoints */
+                .anyRequest().authenticated();
+        /* add JWT token filter */
+        http.addFilterBefore(authTokenFilter(),
+                UsernamePasswordAuthenticationFilter.class
+        );
+    }
+
+    @Bean
+    public CorsFilter corsFilter() {
+        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        final CorsConfiguration config = new CorsConfiguration();
+        config.setAllowCredentials(true);
+        config.addAllowedOrigin("*");
+        config.addAllowedHeader("*");
+        config.addAllowedMethod("*");
+        source.registerCorsConfiguration("/**", config);
+        return new CorsFilter(source);
+    }
+
+}
diff --git a/fda-document-service/services/src/main/java/at/tuwien/exception/DraftRecordCreateException.java b/fda-document-service/services/src/main/java/at/tuwien/exception/DraftRecordCreateException.java
new file mode 100644
index 0000000000000000000000000000000000000000..6b8e7337a1a74d8c3325ae362973d1c49ec10930
--- /dev/null
+++ b/fda-document-service/services/src/main/java/at/tuwien/exception/DraftRecordCreateException.java
@@ -0,0 +1,21 @@
+package at.tuwien.exception;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseStatus(code = HttpStatus.EXPECTATION_FAILED)
+public class DraftRecordCreateException extends Exception {
+
+    public DraftRecordCreateException(String msg) {
+        super(msg);
+    }
+
+    public DraftRecordCreateException(String msg, Throwable thr) {
+        super(msg, thr);
+    }
+
+    public DraftRecordCreateException(Throwable thr) {
+        super(thr);
+    }
+
+}
diff --git a/fda-document-service/services/src/main/java/at/tuwien/gateway/AuthenticationServiceGateway.java b/fda-document-service/services/src/main/java/at/tuwien/gateway/AuthenticationServiceGateway.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc47ce246da851244cf1630b15f493ded20249d8
--- /dev/null
+++ b/fda-document-service/services/src/main/java/at/tuwien/gateway/AuthenticationServiceGateway.java
@@ -0,0 +1,14 @@
+package at.tuwien.gateway;
+
+import org.springframework.security.core.userdetails.UserDetails;
+
+public interface AuthenticationServiceGateway {
+
+    /**
+     * Validates a token
+     *
+     * @param token The token
+     * @return User details on success
+     */
+    UserDetails validate(String token);
+}
diff --git a/fda-document-service/services/src/main/java/at/tuwien/gateway/DocumentGateway.java b/fda-document-service/services/src/main/java/at/tuwien/gateway/DocumentGateway.java
new file mode 100644
index 0000000000000000000000000000000000000000..129d17a458811089db84e589c5b460f509ccfb58
--- /dev/null
+++ b/fda-document-service/services/src/main/java/at/tuwien/gateway/DocumentGateway.java
@@ -0,0 +1,13 @@
+package at.tuwien.gateway;
+
+import at.tuwien.api.document.record.CreateDraftDto;
+import at.tuwien.api.document.record.DraftDto;
+import at.tuwien.exception.DraftRecordCreateException;
+
+public interface DocumentGateway {
+    DraftDto createDraft(CreateDraftDto data, String token) throws DraftRecordCreateException;
+
+    DraftDto reserveDraftDoi(String id, String token) throws DraftRecordCreateException;
+
+    DraftDto findDraft(String id, String token) throws DraftRecordCreateException;
+}
diff --git a/fda-document-service/services/src/main/java/at/tuwien/gateway/impl/AuthenticationServiceGatewayImpl.java b/fda-document-service/services/src/main/java/at/tuwien/gateway/impl/AuthenticationServiceGatewayImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..56d691a6c825b473029c8f1dcd320c949cdcf177
--- /dev/null
+++ b/fda-document-service/services/src/main/java/at/tuwien/gateway/impl/AuthenticationServiceGatewayImpl.java
@@ -0,0 +1,38 @@
+package at.tuwien.gateway.impl;
+
+import at.tuwien.api.user.UserDto;
+import at.tuwien.gateway.AuthenticationServiceGateway;
+import at.tuwien.mapper.UserMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+@Slf4j
+@Service
+public class AuthenticationServiceGatewayImpl implements AuthenticationServiceGateway {
+
+    private final UserMapper userMapper;
+    private final RestTemplate restTemplate;
+
+    @Autowired
+    public AuthenticationServiceGatewayImpl(UserMapper userMapper, RestTemplate restTemplate) {
+        this.userMapper = userMapper;
+        this.restTemplate = restTemplate;
+    }
+
+    @Override
+    public UserDetails validate(String token) {
+        final HttpHeaders headers = new HttpHeaders();
+        headers.set("Authorization", "Bearer " + token);
+        final ResponseEntity<UserDto> response = restTemplate.exchange("/api/auth", HttpMethod.PUT,
+                new HttpEntity<>("", headers), UserDto.class);
+        return userMapper.userDtoToUserDetailsDto(response.getBody());
+    }
+
+}
diff --git a/fda-document-service/services/src/main/java/at/tuwien/gateway/impl/InvenioDocumentGatewayImpl.java b/fda-document-service/services/src/main/java/at/tuwien/gateway/impl/InvenioDocumentGatewayImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..18b9dcd0738ad6aaabcd04a9410df12041a6d7a8
--- /dev/null
+++ b/fda-document-service/services/src/main/java/at/tuwien/gateway/impl/InvenioDocumentGatewayImpl.java
@@ -0,0 +1,76 @@
+package at.tuwien.gateway.impl;
+
+import at.tuwien.api.document.record.CreateDraftDto;
+import at.tuwien.api.document.record.DraftDto;
+import at.tuwien.exception.DraftRecordCreateException;
+import at.tuwien.gateway.DocumentGateway;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.*;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.RestTemplate;
+
+@Slf4j
+@Component
+public class InvenioDocumentGatewayImpl implements DocumentGateway {
+
+    private RestTemplate restTemplate;
+
+    @Autowired
+    public InvenioDocumentGatewayImpl(RestTemplate restTemplate) {
+        this.restTemplate = restTemplate;
+    }
+
+    @Override
+    public DraftDto createDraft(CreateDraftDto data, String token) throws DraftRecordCreateException {
+        log.trace("sending {}", data);
+        final ResponseEntity<DraftDto> response;
+        try {
+            response = restTemplate.exchange("/api/records", HttpMethod.POST,
+                    new HttpEntity<>(data, headers(token)), DraftDto.class);
+        } catch (HttpClientErrorException.BadRequest e) {
+            log.error("Failed to create draft record");
+            throw new DraftRecordCreateException("Failed to create draft record", e);
+        }
+        return response.getBody();
+    }
+
+    @Override
+    public DraftDto reserveDraftDoi(String id, String token) throws DraftRecordCreateException {
+        final ResponseEntity<DraftDto> response;
+        try {
+            response = restTemplate.exchange("/api/records/" + id + "/draft/pids/doi", HttpMethod.POST,
+                    new HttpEntity<>(null, headers(token)), DraftDto.class);
+        } catch (HttpClientErrorException.BadRequest e) {
+            log.error("Failed to reserve draft doi");
+            throw new DraftRecordCreateException("Failed to reserve draft doi", e);
+        }
+        return response.getBody();
+    }
+
+    @Override
+    public DraftDto findDraft(String id, String token) throws DraftRecordCreateException {
+        final ResponseEntity<DraftDto> response;
+        try {
+            response = restTemplate.exchange("/api/records" + id +"/draft", HttpMethod.GET,
+                    new HttpEntity<>(null, headers(token)), DraftDto.class);
+        } catch (HttpClientErrorException.BadRequest e) {
+            log.error("Failed to find draft record");
+            throw new DraftRecordCreateException("Failed to create find record", e);
+        }
+        return response.getBody();
+    }
+
+    /**
+     * Prepares the headers for all requests to authorize with the bearer token.
+     *
+     * @param token The token.
+     * @return The headers.
+     */
+    private HttpHeaders headers(String token) {
+        final HttpHeaders headers = new HttpHeaders();
+        headers.add("Authorization", "Bearer " + token);
+        return headers;
+    }
+}
diff --git a/fda-document-service/services/src/main/java/at/tuwien/mapper/DocumentMapper.java b/fda-document-service/services/src/main/java/at/tuwien/mapper/DocumentMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..0132073b6294cdb9be25a589d4d253fd06ed5b6c
--- /dev/null
+++ b/fda-document-service/services/src/main/java/at/tuwien/mapper/DocumentMapper.java
@@ -0,0 +1,10 @@
+package at.tuwien.mapper;
+
+import org.mapstruct.*;
+
+
+@Mapper(componentModel = "spring")
+public interface DocumentMapper {
+
+
+}
diff --git a/fda-document-service/services/src/main/java/at/tuwien/mapper/UserMapper.java b/fda-document-service/services/src/main/java/at/tuwien/mapper/UserMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..5620c8b3643c2face4747287e24483a56030f1f2
--- /dev/null
+++ b/fda-document-service/services/src/main/java/at/tuwien/mapper/UserMapper.java
@@ -0,0 +1,21 @@
+package at.tuwien.mapper;
+
+import at.tuwien.api.user.GrantedAuthorityDto;
+import at.tuwien.api.user.UserDetailsDto;
+import at.tuwien.api.user.UserDto;
+import at.tuwien.entities.user.User;
+import org.mapstruct.Mapper;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+
+@Mapper(componentModel = "spring")
+public interface UserMapper {
+
+    UserDetailsDto userDtoToUserDetailsDto(UserDto data);
+
+    UserDto userToUserDto(User data);
+
+    default GrantedAuthority grantedAuthorityDtoToGrantedAuthority(GrantedAuthorityDto data) {
+        return new SimpleGrantedAuthority(data.getAuthority());
+    }
+}
diff --git a/fda-document-service/services/src/main/java/at/tuwien/repository/elastic/DatabaseRepository.java b/fda-document-service/services/src/main/java/at/tuwien/repository/elastic/DatabaseRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..aa60a6dbbcdd124de8a38c4098ee43c7115df16f
--- /dev/null
+++ b/fda-document-service/services/src/main/java/at/tuwien/repository/elastic/DatabaseRepository.java
@@ -0,0 +1,9 @@
+package at.tuwien.repository.elastic;
+
+import at.tuwien.entities.database.Database;
+import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository(value = "ElasticDatabaseService")
+public interface DatabaseRepository extends ElasticsearchRepository<Database, Long> {
+}
\ No newline at end of file
diff --git a/fda-document-service/services/src/main/java/at/tuwien/service/DocumentService.java b/fda-document-service/services/src/main/java/at/tuwien/service/DocumentService.java
new file mode 100644
index 0000000000000000000000000000000000000000..48e0de0e77c8929ff76a987037f0417e150ff7bc
--- /dev/null
+++ b/fda-document-service/services/src/main/java/at/tuwien/service/DocumentService.java
@@ -0,0 +1,16 @@
+package at.tuwien.service;
+
+import at.tuwien.api.document.record.CreateDraftDto;
+import at.tuwien.api.document.record.DraftDto;
+import at.tuwien.exception.DraftRecordCreateException;
+
+import java.security.Principal;
+
+public interface DocumentService {
+
+    DraftDto findById(String id, Principal principal) throws DraftRecordCreateException;
+
+    DraftDto create(CreateDraftDto data, Principal principal) throws DraftRecordCreateException;
+
+    DraftDto reserveDoi(String id, Principal principal) throws DraftRecordCreateException;
+}
diff --git a/fda-document-service/services/src/main/java/at/tuwien/service/impl/InvenioDocumentServiceImpl.java b/fda-document-service/services/src/main/java/at/tuwien/service/impl/InvenioDocumentServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..60682bcbccd2dc1e7f3eda4a8ee174485758ffae
--- /dev/null
+++ b/fda-document-service/services/src/main/java/at/tuwien/service/impl/InvenioDocumentServiceImpl.java
@@ -0,0 +1,55 @@
+package at.tuwien.service.impl;
+
+import at.tuwien.api.document.record.CreateDraftDto;
+import at.tuwien.api.document.record.DraftDto;
+import at.tuwien.config.InvenioConfig;
+import at.tuwien.exception.DraftRecordCreateException;
+import at.tuwien.gateway.DocumentGateway;
+import at.tuwien.service.DocumentService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.security.Principal;
+
+@Slf4j
+@Service
+public class InvenioDocumentServiceImpl implements DocumentService {
+
+    private final DocumentGateway documentGateway;
+    private final InvenioConfig invenioConfig;
+
+    @Autowired
+    public InvenioDocumentServiceImpl(DocumentGateway documentGateway, InvenioConfig invenioConfig) {
+        this.documentGateway = documentGateway;
+        this.invenioConfig = invenioConfig;
+    }
+
+    @Override
+    public DraftDto findById(String id, Principal principal) throws DraftRecordCreateException {
+        /* get token */
+        /* remote */
+        return documentGateway.findDraft(id, invenioConfig.getDebugToken());
+    }
+
+    @Override
+    public DraftDto create(CreateDraftDto data, Principal principal) throws DraftRecordCreateException {
+        /* get token */
+        /* remote */
+        final DraftDto document = documentGateway.createDraft(data, invenioConfig.getDebugToken());
+        log.info("Created draft record with id {}", document.getId());
+        log.debug("created draft record {}", document);
+        return document;
+    }
+
+    @Override
+    public DraftDto reserveDoi(String id, Principal principal) throws DraftRecordCreateException {
+        /* get token */
+        /* remote */
+        final DraftDto document = documentGateway.reserveDraftDoi(id, invenioConfig.getDebugToken());
+        log.info("Reserved DOI {} for draft record with id {}", document.getPids().getDoi(), document.getId());
+        log.debug("reserved PID {} for draft record with id {}", document.getPids(), document);
+        return document;
+    }
+
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/links/DoiDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/links/DoiDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..6fe993813def5001b3bb876504f493ec6f222352
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/links/DoiDto.java
@@ -0,0 +1,28 @@
+package at.tuwien.api.document.links;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+import javax.validation.constraints.NotBlank;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class DoiDto {
+
+    @Parameter(name = "client")
+    private String client;
+
+    @NotBlank(message = "identifier is required")
+    @Parameter(name = "identifier")
+    private String identifier;
+
+    @Parameter(name = "provider")
+    private String provider;
+
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/links/DraftLinksDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/links/DraftLinksDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..e3b14bcdc0e788c4ef6e5dd88f025927d25ed2e9
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/links/DraftLinksDto.java
@@ -0,0 +1,42 @@
+package at.tuwien.api.document.links;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class DraftLinksDto {
+
+    @Parameter(name = "latest")
+    private String latest;
+
+    @Parameter(name = "versions")
+    private String versions;
+
+    @JsonProperty("self_html")
+    @Parameter(name = "self html")
+    private String selfHtml;
+
+    @Parameter(name = "publish")
+    private String publish;
+
+    @JsonProperty("latest_html")
+    @Parameter(name = "latest html")
+    private String latestHtml;
+
+    @Parameter(name = "self")
+    private String self;
+
+    @Parameter(name = "files")
+    private String files;
+
+    @JsonProperty("access_links")
+    @Parameter(name = "access links")
+    private String accessLinks;
+
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/links/PersistentIdentifiersDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/links/PersistentIdentifiersDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..c7626b8c85c7a7a604140b1d9ae174f34ecf1959
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/links/PersistentIdentifiersDto.java
@@ -0,0 +1,19 @@
+package at.tuwien.api.document.links;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class PersistentIdentifiersDto {
+
+    @Parameter(name = "doi")
+    private DoiDto doi;
+
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/AffiliationDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/AffiliationDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..b150e6138725a7ef84c350b598d6c81a3c677e9a
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/AffiliationDto.java
@@ -0,0 +1,20 @@
+package at.tuwien.api.document.metadata;
+
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class AffiliationDto {
+
+    @Parameter(name = "id", description = "The organizational or institutional id from the controlled vocabulary.")
+    private String id;
+
+    @Parameter(name = "name", description = "The name of the organisation or institution.")
+    private String name;
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/CreatorDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/CreatorDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..5ead5d487c477829b90bc3cbc353395f33d827c5
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/CreatorDto.java
@@ -0,0 +1,29 @@
+package at.tuwien.api.document.metadata;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class CreatorDto {
+
+    @JsonProperty("person_or_org")
+    @NotNull(message = "person or organization is required")
+    @Parameter(name = "person or organization", description = "The person or organization.")
+    private PersonOrOrganizationDto personOrOrganization;
+
+    @Parameter(name = "role", description = "The role of the person or organisation selected from a customizable " +
+            "controlled vocabulary.")
+    private String role;
+
+    @Parameter(name = "affiliations", description = "Affilations if person_or_org.type is personal.")
+    private List<AffiliationDto> affiliations;
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/IdentifierDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/IdentifierDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..7ef178644d5abf23b3d7c58a5f488a571a026b7c
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/IdentifierDto.java
@@ -0,0 +1,23 @@
+package at.tuwien.api.document.metadata;
+
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+import javax.validation.constraints.NotNull;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class IdentifierDto {
+
+    @NotNull(message = "scheme is required")
+    @Parameter(name = "scheme", description = "The identifier scheme.")
+    private IdentifierTypeDto scheme;
+
+    @NotNull(message = "identifier is required")
+    @Parameter(name = "identifier", description = "Actual value of the identifier.")
+    private String identifier;
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/IdentifierTypeDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/IdentifierTypeDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..282aa63be67ca5a38e6273335a5b41f219317d82
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/IdentifierTypeDto.java
@@ -0,0 +1,29 @@
+package at.tuwien.api.document.metadata;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public enum IdentifierTypeDto {
+
+    @JsonProperty("orcid")
+    ORCID("orcid"),
+
+    @JsonProperty("gnd")
+    GND("gnd"),
+
+    @JsonProperty("isni")
+    ISNI("isni"),
+
+    @JsonProperty("ror")
+    ROR("ror");
+
+    private final String type;
+
+    IdentifierTypeDto(String type) {
+        this.type = type;
+    }
+
+    @Override
+    public String toString() {
+        return type;
+    }
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/MetadataDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/MetadataDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..835a772307ffb0a01484933f34b3874348388802
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/MetadataDto.java
@@ -0,0 +1,52 @@
+package at.tuwien.api.document.metadata;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.util.Date;
+import java.util.List;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class MetadataDto {
+
+    @JsonProperty("resource_type")
+    @NotNull(message = "enabled is required")
+    @Parameter(name = "files enabled", description = "Should (and can) files be attached to this record or not.")
+    private ResourceTypeDto resourceType;
+
+    /**
+     * The field is compatible with 2. Creator in DataCite. In addition we are adding the possiblity of associating a
+     * role (like for contributors). This is specifically for cases where e.g. an editor needs to be credited for the
+     * work, while authors of individual articles will be listed under contributors.
+     */
+    @NotNull(message = "creators is required")
+    @Parameter(name = "creators")
+    private List<CreatorDto> creators;
+
+    /**
+     * The fields is compatible with 3. Title in DataCite. Compared to DataCite, the field does not support specifying
+     * the language of the title.
+     */
+    @NotBlank(message = "title is required")
+    @Parameter(name = "title")
+    private String title;
+
+    /**
+     * The field is compatible 5. PublicationYear in DataCite. In case of time intervals, the earliest date is used
+     * for DataCite.
+     */
+    @JsonProperty("publication_date")
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "UTC+2")
+    @NotNull(message = "publication date is required")
+    @Parameter(name = "publication date")
+    private Date publicationDate;
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/PersonOrOrgTypeDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/PersonOrOrgTypeDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..6eb4b9c2f3c9bc3e6420dedc1321e30f0e2dce8c
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/PersonOrOrgTypeDto.java
@@ -0,0 +1,23 @@
+package at.tuwien.api.document.metadata;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public enum PersonOrOrgTypeDto {
+
+    @JsonProperty("personal")
+    PERSONAL("personal"),
+
+    @JsonProperty("organizational")
+    ORGANIZATIONAL("organizational");
+
+    private final String type;
+
+    PersonOrOrgTypeDto(String type) {
+        this.type = type;
+    }
+
+    @Override
+    public String toString() {
+        return type;
+    }
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/PersonOrOrganizationDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/PersonOrOrganizationDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..67a5514de17cda902ba5544d7c62029aeddf987a
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/PersonOrOrganizationDto.java
@@ -0,0 +1,35 @@
+package at.tuwien.api.document.metadata;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class PersonOrOrganizationDto {
+    
+    @NotNull(message = "type is required")
+    @Parameter(name = "type", description = "The type of name. Either personal or organizational.")
+    private PersonOrOrgTypeDto type;
+
+    @JsonProperty("given_name")
+    @Parameter(name = "given name", description = "Given name(s).")
+    private String givenName;
+
+    @JsonProperty("family_name")
+    @Parameter(name = "family name", description = "Family name.")
+    private String familyName;
+
+    @Parameter(name = "name", description = "The full name of the organisation. For a person, this field is generated from given_name and family_name")
+    private String name;
+
+    @Parameter(name = "identifers", description = "Person or organisation identifiers.")
+    private List<IdentifierDto> identifiers;
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/ResourceTypeDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/ResourceTypeDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..7b6edacf87f54eb54d4e02dc897cf41bbdc5026a
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/metadata/ResourceTypeDto.java
@@ -0,0 +1,24 @@
+package at.tuwien.api.document.metadata;
+
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+import javax.validation.constraints.NotNull;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class ResourceTypeDto {
+
+    /**
+     * When interfacing with Datacite, this field is converted to a format compatible with 10. Resource Type (i.e.
+     * type and subtype). DataCite allows free text for the subtype, however InvenioRDM requires this to come from a
+     * customizable controlled vocabulary.
+     */
+    @NotNull(message = "id is required")
+    @Parameter(name = "id", description = "The resource type id from the controlled vocabulary.")
+    private String id;
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/AccessOptionsDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/AccessOptionsDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..fbb501c9d31c08f1006d524b294231ccbc3378bb
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/AccessOptionsDto.java
@@ -0,0 +1,29 @@
+package at.tuwien.api.document.record;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+import javax.validation.constraints.NotNull;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class AccessOptionsDto {
+
+    @NotNull(message = "record access type is required")
+    @Parameter(name = "record access type")
+    private AccessTypeDto record;
+
+    @NotNull(message = "files is required")
+    @Parameter(name = "files")
+    private FileTypeDto files;
+
+    @Parameter(name = "embargo options")
+    private EmbargoDto embargo;
+
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/AccessTypeDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/AccessTypeDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..9816ba4f9f5967f9551c8d788ac6c27dc21c9210
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/AccessTypeDto.java
@@ -0,0 +1,23 @@
+package at.tuwien.api.document.record;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public enum AccessTypeDto {
+
+    @JsonProperty("public")
+    PUBLIC("public"),
+
+    @JsonProperty("restricted")
+    RESTRICTED("restricted");
+
+    private final String type;
+
+    AccessTypeDto(String type) {
+        this.type = type;
+    }
+
+    @Override
+    public String toString() {
+        return type;
+    }
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/CreateDraftDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/CreateDraftDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..623286d9a2e15c633ba7995712acf696295212b8
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/CreateDraftDto.java
@@ -0,0 +1,31 @@
+package at.tuwien.api.document.record;
+
+import at.tuwien.api.document.metadata.MetadataDto;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+import javax.validation.constraints.NotNull;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class CreateDraftDto {
+
+    @NotNull(message = "access is required")
+    @Parameter(name = "access")
+    private AccessOptionsDto access;
+
+    @NotNull(message = "files options is required")
+    @Parameter(name = "files options")
+    private FilesOptionsDto files;
+
+    @NotNull(message = "metadata is required")
+    @Parameter(name = "metadata")
+    private MetadataDto metadata;
+
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/DraftDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/DraftDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..d754f22fce839fe952e855fff31903dc0194dc27
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/DraftDto.java
@@ -0,0 +1,68 @@
+package at.tuwien.api.document.record;
+
+import at.tuwien.api.document.links.PersistentIdentifiersDto;
+import at.tuwien.api.document.metadata.MetadataDto;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+import javax.validation.constraints.NotNull;
+import java.time.Instant;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class DraftDto {
+
+    @NotNull(message = "access is required")
+    @Parameter(name = "access")
+    private AccessOptionsDto access;
+
+    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX", timezone = "UTC+2")
+    private Instant created;
+
+    @JsonProperty("expires_at")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSSSSS", timezone = "UTC+2")
+    private Instant expiresAt;
+
+    @NotNull(message = "files options is required")
+    @Parameter(name = "files options")
+    private FilesOptionsDto files;
+
+    @NotNull(message = "id is required")
+    @Parameter(name = "id")
+    private String id;
+
+    @JsonProperty("is_published")
+    @NotNull(message = "is published is required")
+    @Parameter(name = "is published")
+    private Boolean isPublished;
+
+    @NotNull(message = "metadata is required")
+    @Parameter(name = "metadata")
+    private MetadataDto metadata;
+
+    @JsonProperty("revision_id")
+    @NotNull(message = "revision id is required")
+    @Parameter(name = "revision id")
+    private Long revisionId;
+
+    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX", timezone = "UTC+2")
+    @Parameter(name = "updated date")
+    private Instant updated;
+
+    @NotNull(message = "versions is required")
+    @Parameter(name = "revisions")
+    private DraftVersionsDto versions;
+
+    @NotNull(message = "pids is required")
+    @Parameter(name = "pids")
+    private PersistentIdentifiersDto pids;
+
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/DraftVersionsDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/DraftVersionsDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae3109911b5bc2123757519e05ad2427aa56bacd
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/DraftVersionsDto.java
@@ -0,0 +1,30 @@
+package at.tuwien.api.document.record;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+import javax.validation.constraints.NotNull;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class DraftVersionsDto {
+
+    @Parameter(name = "index")
+    private Long index;
+
+    @JsonProperty("is_latest")
+    @Parameter(name = "is latest version")
+    private Boolean isLatest;
+
+    @JsonProperty("is_latest_draft")
+    @Parameter(name = "is latest draft")
+    private Boolean isLatestDraft;
+
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/EmbargoDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/EmbargoDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..82e417393a43cab4046b82251c97955e1436aa18
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/EmbargoDto.java
@@ -0,0 +1,29 @@
+package at.tuwien.api.document.record;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+import javax.validation.constraints.NotNull;
+import java.util.Date;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class EmbargoDto {
+
+    @NotNull(message = "embargo active is required")
+    @Parameter(name = "embargo active")
+    private Boolean active;
+
+    @Parameter(name = "embargo until date")
+    private Date until;
+
+    @Parameter(name = "embargo explanation")
+    private String reason;
+
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/FileTypeDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/FileTypeDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..97536d9081beea03428adb89b02a97d5169f063f
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/FileTypeDto.java
@@ -0,0 +1,23 @@
+package at.tuwien.api.document.record;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public enum FileTypeDto {
+
+    @JsonProperty("public")
+    PUBLIC("public"),
+
+    @JsonProperty("restricted")
+    RESTRICTED("restricted");
+
+    private final String type;
+
+    FileTypeDto(String type) {
+        this.type = type;
+    }
+
+    @Override
+    public String toString() {
+        return type;
+    }
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/FilesOptionsDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/FilesOptionsDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..7ccebb72a644a29c53bcd463574fe8053c3919e4
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/FilesOptionsDto.java
@@ -0,0 +1,24 @@
+package at.tuwien.api.document.record;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+import javax.validation.constraints.NotNull;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class FilesOptionsDto {
+
+    @NotNull(message = "enabled is required")
+    @Parameter(name = "files enabled", description = "Should (and can) files be attached to this record or not.")
+    private Boolean enabled;
+
+    @Parameter(name = "files preview", description = "Filename of file to be previewed by default.")
+    private String default_preview;
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/ModifyDraftDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/ModifyDraftDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..6e1a8af30e4c04c1e69bee201a1ef2b790f1c793
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/ModifyDraftDto.java
@@ -0,0 +1,22 @@
+package at.tuwien.api.document.record;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+import javax.validation.constraints.NotNull;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class ModifyDraftDto {
+
+    @NotNull(message = "identifier is required")
+    @Parameter(name = "identifier", description = "Identifier of the record, e.g. 4d0ns-ntd89")
+    private String id;
+
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/UpdateDraftDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/UpdateDraftDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..cce7e853f013fa2b7a069b42fcd8c82f79803437
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/UpdateDraftDto.java
@@ -0,0 +1,35 @@
+package at.tuwien.api.document.record;
+
+import at.tuwien.api.document.metadata.MetadataDto;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+import javax.validation.constraints.NotNull;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class UpdateDraftDto {
+
+    @NotNull(message = "identifier is required")
+    @Parameter(name = "identifier", description = "Identifier of the record, e.g. 4d0ns-ntd89")
+    private String id;
+    
+    @NotNull(message = "access is required")
+    @Parameter(name = "access")
+    private AccessOptionsDto access;
+
+    @NotNull(message = "files options is required")
+    @Parameter(name = "files options")
+    private FilesOptionsDto files;
+
+    @NotNull(message = "metadata is required")
+    @Parameter(name = "metadata")
+    private MetadataDto metadata;
+
+}