diff --git a/.invenio/.gitignore b/.invenio/.gitignore
index ed8ebf583f771da9150c35db3955987b7d757904..150c6f7559b9b2d2589bf19527624f975d3b8d81 100644
--- a/.invenio/.gitignore
+++ b/.invenio/.gitignore
@@ -1 +1,3 @@
-__pycache__
\ No newline at end of file
+__pycache__
+
+features.csv
\ No newline at end of file
diff --git a/.invenio/api_authentication/configuration.py b/.invenio/api_authentication/configuration.py
index a35f4efa83f8e7872add91b87e3820876cd4a034..2638b5e36f20bba23c9228abf90fd54e7d31fd14 100644
--- a/.invenio/api_authentication/configuration.py
+++ b/.invenio/api_authentication/configuration.py
@@ -46,7 +46,7 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)):
     def __init__(self):
         """Constructor"""
         # Default Base url
-        self.host = "http://localhost:9097"
+        self.host = "http://localhost:9095"
         # Temp file folder for downloading files
         self.temp_folder_path = None
 
diff --git a/.invenio/api_container/configuration.py b/.invenio/api_container/configuration.py
index b93a7ea5d39b5f221247b3f99ad776ebdc36311c..23d21b83810a226c542b2172f81bcb8fc607ce8b 100644
--- a/.invenio/api_container/configuration.py
+++ b/.invenio/api_container/configuration.py
@@ -46,7 +46,7 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)):
     def __init__(self):
         """Constructor"""
         # Default Base url
-        self.host = "http://localhost:9091"
+        self.host = "http://localhost:9095"
         # Temp file folder for downloading files
         self.temp_folder_path = None
 
diff --git a/.invenio/api_database/configuration.py b/.invenio/api_database/configuration.py
index 758efb3300d9922238fe802fcd68b162b1d5e3ad..5ee4406b932b0def43900eedf1c962a85da65c16 100644
--- a/.invenio/api_database/configuration.py
+++ b/.invenio/api_database/configuration.py
@@ -46,7 +46,7 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)):
     def __init__(self):
         """Constructor"""
         # Default Base url
-        self.host = "http://localhost:9092"
+        self.host = "http://localhost:9095"
         # Temp file folder for downloading files
         self.temp_folder_path = None
 
diff --git a/.invenio/api_document/configuration.py b/.invenio/api_document/configuration.py
index bb7e50accfb91635831106693aeab48db409982c..3acecd4c60c1c9dd69a43e7a6e6c8ca2b748127f 100644
--- a/.invenio/api_document/configuration.py
+++ b/.invenio/api_document/configuration.py
@@ -46,7 +46,7 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)):
     def __init__(self):
         """Constructor"""
         # Default Base url
-        self.host = "http://localhost:9099"
+        self.host = "http://localhost:9095"
         # Temp file folder for downloading files
         self.temp_folder_path = None
 
diff --git a/.invenio/api_identifier/configuration.py b/.invenio/api_identifier/configuration.py
index 7845c1cc68b9f2bd55aadd1c1facc1520d51a416..28b5cf87552aa2b12278480c89b594d8332d847b 100644
--- a/.invenio/api_identifier/configuration.py
+++ b/.invenio/api_identifier/configuration.py
@@ -46,7 +46,7 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)):
     def __init__(self):
         """Constructor"""
         # Default Base url
-        self.host = "http://localhost:9096"
+        self.host = "http://localhost:9095"
         # Temp file folder for downloading files
         self.temp_folder_path = None
 
diff --git a/.invenio/api_query/api/table_data_endpoint_api.py b/.invenio/api_query/api/table_data_endpoint_api.py
index 12101dabc2a0badc252bd2c4801258eed30cd414..34b6434bf0480fb38772c7920fab94c0754393de 100644
--- a/.invenio/api_query/api/table_data_endpoint_api.py
+++ b/.invenio/api_query/api/table_data_endpoint_api.py
@@ -259,7 +259,7 @@ class TableDataEndpointApi(object):
         auth_settings = []  # noqa: E501
 
         return self.api_client.call_api(
-            '/api/container/{id}/database/{databaseId}/table/{tableId}/data', 'HEAD',
+            '/api/container/{id}/database/{databaseId}/table/{tableId}/data', 'GET',
             path_params,
             query_params,
             header_params,
@@ -380,7 +380,7 @@ class TableDataEndpointApi(object):
         auth_settings = []  # noqa: E501
 
         return self.api_client.call_api(
-            '/api/container/{id}/database/{databaseId}/table/{tableId}/data', 'GET',
+            '/api/container/{id}/database/{databaseId}/table/{tableId}/data', 'HEAD',
             path_params,
             query_params,
             header_params,
diff --git a/.invenio/api_query/configuration.py b/.invenio/api_query/configuration.py
index 1b566374df8cf6e9fac26244c8a29c2ffd3e7f1d..2991fff8bf4bb94a0f13898b2c1332ee3644ca45 100644
--- a/.invenio/api_query/configuration.py
+++ b/.invenio/api_query/configuration.py
@@ -46,7 +46,7 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)):
     def __init__(self):
         """Constructor"""
         # Default Base url
-        self.host = "http://localhost:9093"
+        self.host = "http://localhost:9095"
         # Temp file folder for downloading files
         self.temp_folder_path = None
 
diff --git a/.invenio/api_table/configuration.py b/.invenio/api_table/configuration.py
index f24b34599fae66af44bb081f816e9f88a90bd103..557adf4db5a7409e3736e03ecbe0380531dac8a6 100644
--- a/.invenio/api_table/configuration.py
+++ b/.invenio/api_table/configuration.py
@@ -46,7 +46,7 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)):
     def __init__(self):
         """Constructor"""
         # Default Base url
-        self.host = "http://localhost:9094"
+        self.host = "http://localhost:9095"
         # Temp file folder for downloading files
         self.temp_folder_path = None
 
diff --git a/.invenio/analyze.ipynb b/.invenio/deposit.ipynb
similarity index 82%
rename from .invenio/analyze.ipynb
rename to .invenio/deposit.ipynb
index 542a3613a68536dffacff19325129ed71a2bbda4..6fe7d9c7706b1dfac15d7cbff01c8769512480ac 100644
--- a/.invenio/analyze.ipynb
+++ b/.invenio/deposit.ipynb
@@ -2,15 +2,11 @@
  "cells": [
   {
    "cell_type": "markdown",
+   "source": [],
    "metadata": {
-    "collapsed": true,
-    "pycharm": {
-     "name": "#%% md\n"
-    }
+    "collapsed": false
    },
-   "source": [
-    "# Test"
-   ]
+   "outputs": []
   }
  ],
  "metadata": {
diff --git a/.invenio/dev.py b/.invenio/dev.py
old mode 100644
new mode 100755
index aa0cb1af32c8d6baf25176689b9de61bc2186f00..81a94da41ad4d186fda1f9ec340391ceae4e7f9e
--- a/.invenio/dev.py
+++ b/.invenio/dev.py
@@ -1,67 +1,34 @@
 #!/usr/bin/env python3
-import json
-
+import re
+import csv
 import requests
 
-from api_authentication.api.authentication_endpoint_api import AuthenticationEndpointApi
-from api_authentication.api.user_endpoint_api import UserEndpointApi
-from api_container.api.container_endpoint_api import ContainerEndpointApi
-from api_database.api.container_database_endpoint_api import ContainerDatabaseEndpointApi
+doi = '10.5281/zenodo.5649276'
+headers = {
+    'Authorize': 'Bearer djCvqkoOW69keHajybZiwE8bBjyir2QSZOLKpAtc4S1Wp17KXgcHmMoWJwft' 
+}
 
-authentication = AuthenticationEndpointApi()
-user = UserEndpointApi()
-container = ContainerEndpointApi()
-database = ContainerDatabaseEndpointApi()
+# Resolve DOI
+response = requests.get('https://doi.org/' + doi)
+id = re.findall('/([a-z0-9-]+)$', response.url)[0]
+host = re.findall('^https?:\/\/([a-z0-9]+\.[a-z]+)', response.url)[0]
+print("Resolved DOI to", host, "and record id", id)
 
-# # Create account
-# response = user.register({
-#     'username': 'mweise',
-#     'password': 'fda',
-#     'email': 'martin.weise@tuwien.ac.at'
-# })
-# print('Created account with username %s' % response.username)
-#
-# # Create authentication
-# response = authentication.authenticate_user1({
-#     'username': 'mweise',
-#     'password': 'fda'
-# })
-# container.api_client.default_headers = {
-#     'Authorization': 'Bearer ' + response.token
-# }
-# database.api_client.default_headers = {
-#     'Authorization': 'Bearer ' + response.token
-# }
-#
-# # Create container
-# response = container.create1({
-#     'name': 'MIR ' + str(uuid.uuid1()),
-#     'repository': 'mariadb',
-#     'tag': '10.5'
-# })
-# cid = response.id
-# print('Created container with id %d' % cid)
-#
-# # Start container
-# response = container.modify({
-#     'action': 'START'
-# }, cid)
-# time.sleep(5)
-# print('Started container with id %d' % cid)
-#
-# # Create database
-# response = database.create({
-#     'name': 'MIR ' + str(uuid.uuid1()),
-#     'description': 'Music Information Retrieval',
-#     'is_public': True
-# }, cid)
-# dbid = response.id
-# print('Created database with id %d' % dbid)
+# Find files
+url = 'https://' + host + '/api/records/' + id
+response = requests.get(url, headers=headers)
+record = response.json()
 
-# Analyse Table
-response = requests.post('http://localhost:5000/api/analyse/determinedt', json={
-    'filepath': '/tmp/test.csv',
-})
-data = json.loads(response.content)
-print('Determined data types')
-print(response)
+# Write some .csv
+i = 0
+with open('./features.csv', 'w') as f:
+    writer = csv.writer(f)
+    writer.writerow(['key', 'size', 'link'])
+    for file in record['files']:
+        requests.get(file['links']['self'])
+        print("... feature extract from", file['links']['self'])
+        writer.writerow([file['key'], file['size'], file['links']['self']])
+        i += 1
+        if i > 10:
+            break
+print("Generated a feature .csv")
diff --git a/.invenio/feature_extract.ipynb b/.invenio/feature_extract.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..9de40c112c0b206df177dac3ba2fd34bb6819f52
--- /dev/null
+++ b/.invenio/feature_extract.ipynb
@@ -0,0 +1,367 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "collapsed": true,
+    "pycharm": {
+     "name": "#%% md\n"
+    }
+   },
+   "source": [
+    "# Feature Extraction & Deposit\n",
+    "\n",
+    "In this notebook we define an example of creating a database from a .csv and perform feature extraction of audio files. The APIs are auto-generated from the Swagger Endpoint documentations using [`generate.sh`](https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-docs/-/blob/master/swagger/generate.sh). Steps we perform:\n",
+    "\n",
+    "  1. Download a music file from a public repository\n",
+    "  2. Perform feature extraction\n",
+    "  3. Create an account at DBRepo\n",
+    "  4. Create an authentication token\n",
+    "  5. Create a mariadb container\n",
+    "  6. Start the mariadb container\n",
+    "  7. Create a database within the mariadb container\n",
+    "  8. Import the feature .csv (manually)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 20,
+   "outputs": [],
+   "source": [
+    "import os.path\n",
+    "import uuid\n",
+    "import time\n",
+    "import re\n",
+    "import csv\n",
+    "import requests as rq\n",
+    "from api_authentication.api.authentication_endpoint_api import AuthenticationEndpointApi\n",
+    "from api_authentication.api.user_endpoint_api import UserEndpointApi\n",
+    "from api_container.api.container_endpoint_api import ContainerEndpointApi\n",
+    "from api_database.api.container_database_endpoint_api import ContainerDatabaseEndpointApi\n",
+    "from api_table.api.table_endpoint_api import TableEndpointApi\n",
+    "\n",
+    "authentication = AuthenticationEndpointApi()\n",
+    "user = UserEndpointApi()\n",
+    "container = ContainerEndpointApi()\n",
+    "database = ContainerDatabaseEndpointApi()\n",
+    "table = TableEndpointApi()\n",
+    "\n",
+    "doi = \"10.5281/zenodo.5649276\"\n",
+    "email = \"some@example.com\""
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "markdown",
+   "source": [
+    "## 1. Download wav\n",
+    "\n",
+    "Resolve the DOI to URI"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 21,
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Resolved DOI to zenodo.org and record id 5649276\n"
+     ]
+    }
+   ],
+   "source": [
+    "response = rq.get(\"https://doi.org/\" + doi)\n",
+    "id = re.findall(\"/([a-z0-9-]+)$\", response.url)[0]\n",
+    "host = re.findall(\"^https?:\\/\\/([a-z0-9]+\\.[a-z]+)\", response.url)[0]\n",
+    "print(\"Resolved DOI to\", host, \"and record id\", id)"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "markdown",
+   "source": [
+    "## 2. Perform feature extraction"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 22,
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "... feature extract from https://zenodo.org/api/files/22d69a63-2aff-47ae-b818-be78a23e9889/colive.0044_20200518133554_1_m4a_1.wav\n",
+      "... feature extract from https://zenodo.org/api/files/22d69a63-2aff-47ae-b818-be78a23e9889/colive.0044_20200518133554_2_m4a_1.wav\n",
+      "... feature extract from https://zenodo.org/api/files/22d69a63-2aff-47ae-b818-be78a23e9889/colive.0066_20200611134530_1_m4a_0.wav\n",
+      "... feature extract from https://zenodo.org/api/files/22d69a63-2aff-47ae-b818-be78a23e9889/colive.0066_20200611134530_2_m4a_0.wav\n",
+      "... feature extract from https://zenodo.org/api/files/22d69a63-2aff-47ae-b818-be78a23e9889/colive.0066_20200612072315_1_m4a_0.wav\n",
+      "... feature extract from https://zenodo.org/api/files/22d69a63-2aff-47ae-b818-be78a23e9889/colive.0066_20200612072315_2_m4a_0.wav\n",
+      "... feature extract from https://zenodo.org/api/files/22d69a63-2aff-47ae-b818-be78a23e9889/colive.0066_20200613082517_1_m4a_0.wav\n",
+      "... feature extract from https://zenodo.org/api/files/22d69a63-2aff-47ae-b818-be78a23e9889/colive.0066_20200613082517_2_m4a_0.wav\n",
+      "... feature extract from https://zenodo.org/api/files/22d69a63-2aff-47ae-b818-be78a23e9889/colive.0066_20200614080017_1_m4a_0.wav\n",
+      "... feature extract from https://zenodo.org/api/files/22d69a63-2aff-47ae-b818-be78a23e9889/colive.0066_20200614080017_2_m4a_0.wav\n",
+      "... feature extract from https://zenodo.org/api/files/22d69a63-2aff-47ae-b818-be78a23e9889/colive.0066_20200615070238_1_m4a_0.wav\n",
+      "Generated a feature .csv in your home directory\n"
+     ]
+    }
+   ],
+   "source": [
+    "response = rq.get(\"https://\" + host + \"/api/records/\" + id)\n",
+    "record = response.json()\n",
+    "\n",
+    "i = 0\n",
+    "with open(os.path.expanduser(\"~/features.csv\"), \"w\") as f:\n",
+    "    writer = csv.writer(f)\n",
+    "    writer.writerow([\"key\", \"size\", \"link\"])\n",
+    "    for file in record[\"files\"]:\n",
+    "        rq.get(file[\"links\"][\"self\"])\n",
+    "        print(\"... feature extract from\", file[\"links\"][\"self\"])\n",
+    "        writer.writerow([file[\"key\"], file[\"size\"], file[\"links\"][\"self\"]])\n",
+    "        i += 1\n",
+    "        if i > 10:\n",
+    "            break\n",
+    "print(\"Generated a feature .csv in your home directory\")"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "markdown",
+   "source": [
+    "## 3. Create an account at DBRepo"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 23,
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "{'authorities': [{'authority': 'ROLE_RESEARCHER'}],\n",
+      " 'containers': None,\n",
+      " 'databases': None,\n",
+      " 'email': 'martinweiseat@gmail.com',\n",
+      " 'firstname': None,\n",
+      " 'id': 2,\n",
+      " 'identifiers': None,\n",
+      " 'lastname': None,\n",
+      " 'titles_after': None,\n",
+      " 'titles_before': None,\n",
+      " 'username': 'user'}\n"
+     ]
+    }
+   ],
+   "source": [
+    "response = user.register({\n",
+    "    \"username\": \"user\",\n",
+    "    \"password\": \"user\",\n",
+    "    \"email\": email\n",
+    "})\n",
+    "print(response)"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "markdown",
+   "source": [
+    "## 4. Create an authentication token"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 24,
+   "outputs": [],
+   "source": [
+    "response = authentication.authenticate_user1({\n",
+    "    \"username\": \"user\",\n",
+    "    \"password\": \"user\"\n",
+    "})\n",
+    "container.api_client.default_headers = {\"Authorization\": \"Bearer \" + response.token}\n",
+    "database.api_client.default_headers = {\"Authorization\": \"Bearer \" + response.token}\n",
+    "table.api_client.default_headers = {\"Authorization\": \"Bearer \" + response.token}"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "markdown",
+   "source": [
+    "## 5. Create a mariadb container"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 25,
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "{'hash': 'f5a649a71aae3748e62228721c44627ffc866f665d677bb890c37b9111590ffa',\n",
+      " 'id': 2,\n",
+      " 'internal_name': 'fda-userdb-mir-1010b964-f6fa-11ec-9f77-64bc58900b78',\n",
+      " 'is_public': None,\n",
+      " 'name': 'MIR 1010b964-f6fa-11ec-9f77-64bc58900b78'}\n"
+     ]
+    }
+   ],
+   "source": [
+    "response = container.create1({\n",
+    "    \"name\": \"MIR \" + str(uuid.uuid1()),\n",
+    "    \"repository\": \"mariadb\",\n",
+    "    \"tag\": \"10.5\"\n",
+    "})\n",
+    "container_id = response.id\n",
+    "print(response)"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "markdown",
+   "source": [
+    "## 6. Start the mariadb container"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 26,
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "{'hash': 'f5a649a71aae3748e62228721c44627ffc866f665d677bb890c37b9111590ffa',\n",
+      " 'id': 2,\n",
+      " 'internal_name': 'fda-userdb-mir-1010b964-f6fa-11ec-9f77-64bc58900b78',\n",
+      " 'is_public': None,\n",
+      " 'name': 'MIR 1010b964-f6fa-11ec-9f77-64bc58900b78'}\n"
+     ]
+    }
+   ],
+   "source": [
+    "response = container.modify({\n",
+    "    \"action\": \"START\"\n",
+    "}, container_id)\n",
+    "time.sleep(5)\n",
+    "print(response)"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "markdown",
+   "source": [
+    "## 7. Create a database within the mariadb container"
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 27,
+   "outputs": [],
+   "source": [
+    "response = database.create({\n",
+    "    \"name\": \"MIR \" + str(uuid.uuid1()),\n",
+    "    \"description\": \"Music Information Retrieval\",\n",
+    "    \"is_public\": True\n",
+    "}, container_id)\n",
+    "database_id = response.id"
+   ],
+   "metadata": {
+    "collapsed": false,
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   }
+  },
+  {
+   "cell_type": "markdown",
+   "source": [
+    "## 8. Import the feature .csv\n",
+    "\n",
+    "Now open [http://localhost:3000/](http://localhost:3000/) and import the .csv file by clicking the database. After successful creation of the table, come back here."
+   ],
+   "metadata": {
+    "collapsed": false
+   }
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 2
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython2",
+   "version": "2.7.6"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 0
+}
\ No newline at end of file
diff --git a/.invenio/requirements.txt b/.invenio/requirements.txt
index 47f78a7d8881dd86110db66b62b8dbe2d9f2332c..cead3141b668dc1ff86be21106936bad117b97a9 100644
--- a/.invenio/requirements.txt
+++ b/.invenio/requirements.txt
@@ -1,2 +1 @@
-invenio-client==0.1.0
-six==1.16.0
\ No newline at end of file
+requests==2.28.0
\ No newline at end of file
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
index 2436b9748bc4e11979c02f8f947e99e481da8287..395e77b5a34dafbf16d3b1bd1026029c1f5348d8 100644
--- 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
@@ -1,7 +1,7 @@
 package at.tuwien.endpoints;
 
 import at.tuwien.api.document.record.CreateDraftDto;
-import at.tuwien.api.document.record.DraftDto;
+import at.tuwien.api.document.record.RecordDto;
 import at.tuwien.exception.DraftRecordCreateException;
 import at.tuwien.service.DocumentService;
 import io.swagger.v3.oas.annotations.Operation;
@@ -20,9 +20,8 @@ import java.security.Principal;
 
 
 @Log4j2
-@RestController
 @CrossOrigin(origins = "*")
-@ControllerAdvice
+@RestController
 @RequestMapping("/api/document")
 public class DocumentEndpoint {
 
@@ -37,9 +36,9 @@ public class DocumentEndpoint {
     @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,
+    public ResponseEntity<RecordDto> create(@NotNull @Valid @RequestBody CreateDraftDto data,
                                            @NotNull Principal principal) throws DraftRecordCreateException {
-        final DraftDto document = documentService.create(data, principal);
+        final RecordDto document = documentService.create(data, principal);
         return ResponseEntity.status(HttpStatus.CREATED)
                 .body(document);
     }
@@ -48,22 +47,33 @@ public class DocumentEndpoint {
     @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,
+    public ResponseEntity<RecordDto> find(@NotNull @PathVariable("id") String documentId,
                                          @NotNull Principal principal) throws DraftRecordCreateException {
-        final DraftDto document = documentService.findById(documentId, principal);
+        final RecordDto 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);
     }
 
+    @PutMapping("/{id}/publish")
+    @PreAuthorize("hasRole('ROLE_RESEARCHER')")
+    @Transactional(readOnly = true)
+    @Operation(summary = "Publish a draft", security = @SecurityRequirement(name = "bearerAuth"))
+    public ResponseEntity<RecordDto> publish(@NotNull @PathVariable("id") String documentId,
+                                         @NotNull Principal principal) throws DraftRecordCreateException {
+        final RecordDto document = documentService.publish(documentId, principal);
+        return ResponseEntity.status(HttpStatus.ACCEPTED)
+                .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,
+    public ResponseEntity<RecordDto> reserve(@NotNull @PathVariable("id") String documentId,
                                             @NotNull Principal principal) throws DraftRecordCreateException {
-        final DraftDto document = documentService.reserveDoi(documentId, principal);
+        final RecordDto 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/endpoints/FileEndpoint.java b/fda-document-service/rest-service/src/main/java/at/tuwien/endpoints/FileEndpoint.java
index 5457e3c67a4485f99eb79fbf6c1241d5e189b960..402d37ed3b6b1a25360b845fda3edb8081377c6f 100644
--- a/fda-document-service/rest-service/src/main/java/at/tuwien/endpoints/FileEndpoint.java
+++ b/fda-document-service/rest-service/src/main/java/at/tuwien/endpoints/FileEndpoint.java
@@ -1,6 +1,8 @@
 package at.tuwien.endpoints;
 
-import at.tuwien.api.document.file.FileStartDto;
+import at.tuwien.api.document.file.FileDto;
+import at.tuwien.exception.FileUploadException;
+import at.tuwien.exception.CommitFileUploadException;
 import at.tuwien.exception.DraftRecordCreateException;
 import at.tuwien.service.FileService;
 import io.swagger.v3.oas.annotations.Operation;
@@ -12,6 +14,7 @@ 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 org.springframework.web.multipart.MultipartFile;
 
 import javax.validation.constraints.NotNull;
 import java.security.Principal;
@@ -20,7 +23,6 @@ import java.security.Principal;
 @Log4j2
 @RestController
 @CrossOrigin(origins = "*")
-@ControllerAdvice
 @RequestMapping("/api/document/{id}/file")
 public class FileEndpoint {
 
@@ -34,11 +36,14 @@ public class FileEndpoint {
     @PostMapping
     @PreAuthorize("hasRole('ROLE_RESEARCHER')")
     @Transactional(readOnly = true)
-    @Operation(summary = "Start draft files", security = @SecurityRequirement(name = "bearerAuth"))
-    public ResponseEntity<FileStartDto> start(@NotNull @PathVariable("id") String documentId,
-                                           @NotNull Principal principal) throws DraftRecordCreateException {
-        final FileStartDto document = fileService.start(documentId, principal);
-        return ResponseEntity.status(HttpStatus.CREATED)
+    @Operation(summary = "Upload file", security = @SecurityRequirement(name = "bearerAuth"))
+    public ResponseEntity<FileDto> uploadFile(@NotNull @PathVariable("id") String documentId,
+                                              @NotNull @RequestParam("file") MultipartFile file,
+                                              @NotNull Principal principal)
+            throws DraftRecordCreateException, CommitFileUploadException, FileUploadException,
+            org.apache.tomcat.util.http.fileupload.FileUploadException {
+        final FileDto document = fileService.uploadFile(documentId, file, principal);
+        return ResponseEntity.status(HttpStatus.ACCEPTED)
                 .body(document);
     }
 
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
index 46f56dc08b4dff9989e3e1d942e2253678759f7a..6cc0944799641089de2168f1d4338b96254ddb11 100644
--- a/fda-document-service/rest-service/src/main/resources/application-docker.yml
+++ b/fda-document-service/rest-service/src/main/resources/application-docker.yml
@@ -30,5 +30,6 @@ eureka:
 fda:
   mount.path: /tmp
   ready.path: /ready
+  gateway.endpoint: http://fda-gateway-service:9095
   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
index 47db505983d03a94640962f3b394da6c91bd3ac7..bf035c9f11d39d0f054bd52677fae08c245eac85 100644
--- a/fda-document-service/rest-service/src/main/resources/application.yml
+++ b/fda-document-service/rest-service/src/main/resources/application.yml
@@ -7,7 +7,7 @@ spring:
     username: postgres
     password: postgres
   jpa:
-    show-sql: false
+    show-sql: true
     database-platform: org.hibernate.dialect.PostgreSQLDialect
     hibernate:
       ddl-auto: validate
@@ -16,7 +16,6 @@ spring:
     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"
@@ -31,5 +30,6 @@ eureka:
 fda:
   mount.path: /tmp
   ready.path: ./ready
+  gateway.endpoint: http://localhost:9095
   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/test/java/at/tuwien/BaseUnitTest.java b/fda-document-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java
index 7f4f0cc7ebc0635d6e11bbccd62c25dbae8dd6da..c772a6be5d7e3f96631d333d187ba7fcff475af5 100644
--- 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
@@ -2,6 +2,8 @@ package at.tuwien;
 
 import at.tuwien.api.document.metadata.*;
 import at.tuwien.api.document.record.*;
+import at.tuwien.api.user.UserDetailsDto;
+import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.test.context.TestPropertySource;
 
 import java.time.Instant;
@@ -11,30 +13,58 @@ import java.util.List;
 @TestPropertySource(locations = "classpath:application.properties")
 public abstract class BaseUnitTest {
 
+    public final static Long USER_1_ID = 1L;
     public final static String USER_1_USERNAME = "junit";
 
+    public final static UserDetails USER_1_DETAILS = UserDetailsDto.builder()
+            .id(USER_1_ID)
+            .username(USER_1_USERNAME)
+            .build();
+
     public final static AccessTypeDto DOCUMENT_1_RECORD_TYPE = AccessTypeDto.PUBLIC;
     public final static FileTypeDto DOCUMENT_1_FILE_TYPE = FileTypeDto.PUBLIC;
 
+    public final static AccessTypeDto DOCUMENT_2_RECORD_TYPE = AccessTypeDto.PUBLIC;
+    public final static FileTypeDto DOCUMENT_2_FILE_TYPE = FileTypeDto.RESTRICTED;
+
     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 AccessOptionsDto DOCUMENT_2_ACCESS_OPTIONS = AccessOptionsDto.builder()
+            .record(DOCUMENT_2_RECORD_TYPE)
+            .files(DOCUMENT_2_FILE_TYPE)
+            .build();
+
+    public final static Boolean DOCUMENT_1_FILES_ENABLED = false;
+
+    public final static Boolean DOCUMENT_2_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 FilesOptionsDto DOCUMENT_2_FILES_OPTIONS = FilesOptionsDto.builder()
+            .enabled(DOCUMENT_2_FILES_ENABLED)
+            .build();
+
+    public final static String DOCUMENT_1_TITLE = "Public Test-Record";
     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 String DOCUMENT_2_TITLE = "Restricted Test-Record";
+    public final static String DOCUMENT_2_RESOURCE_TYPE_TYPE = "other";
+    public final static Date DOCUMENT_2_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 ResourceTypeDto DOCUMENT_2_RESOURCE_TYPE = ResourceTypeDto.builder()
+            .id(DOCUMENT_2_RESOURCE_TYPE_TYPE)
+            .build();
+
     public final static String IDENTIFIER_1_IDENTIFIER = "0000-0003-4216-302X";
     public final static IdentifierTypeDto IDENTIFIER_1_TYPE = IdentifierTypeDto.ORCID;
 
@@ -72,10 +102,23 @@ public abstract class BaseUnitTest {
             .creators(List.of(CREATOR_1))
             .build();
 
+    public final static MetadataDto DOCUMENT_2_METADATA = MetadataDto.builder()
+            .title(DOCUMENT_2_TITLE)
+            .resourceType(DOCUMENT_2_RESOURCE_TYPE)
+            .publicationDate(DOCUMENT_2_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();
 
+    public final static CreateDraftDto DOCUMENT_2_CREATE_DRAFT = CreateDraftDto.builder()
+            .access(DOCUMENT_2_ACCESS_OPTIONS)
+            .files(DOCUMENT_2_FILES_OPTIONS)
+            .metadata(DOCUMENT_2_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
index 0965a30b1e3fe46573e7e50f798b044d9af81cc4..534038dbadbb0e1a3224c5d092719c825be0d1d1 100644
--- 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
@@ -1,13 +1,52 @@
 package at.tuwien.endpoint;
 
 import at.tuwien.BaseUnitTest;
+import at.tuwien.api.document.record.CreateDraftDto;
+import at.tuwien.api.document.record.RecordDto;
+import at.tuwien.endpoints.DocumentEndpoint;
+import at.tuwien.exception.DraftRecordCreateException;
+import at.tuwien.gateway.AuthenticationServiceGateway;
+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.boot.test.mock.mockito.MockBean;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.test.context.support.WithMockUser;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 
+import java.security.Principal;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.when;
+
 @ExtendWith(SpringExtension.class)
 @SpringBootTest
 public class DocumentEndpointUnitTest extends BaseUnitTest {
 
+    @Autowired
+    private DocumentEndpoint documentEndpoint;
+
+    @MockBean
+    private AuthenticationServiceGateway authenticationServiceGateway;
+
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = {"ROLE_RESEARCHER"})
+    public void create_succeed() throws DraftRecordCreateException {
+        final CreateDraftDto request = DOCUMENT_1_CREATE_DRAFT;
+        final Principal principal = new BasicUserPrincipal(USER_1_USERNAME);
+
+        /* mock */
+        when(authenticationServiceGateway.validate(anyString()))
+                .thenReturn(USER_1_DETAILS);
+
+        /* test */
+        final ResponseEntity<RecordDto> response = documentEndpoint.create(request, principal);
+        assertEquals(HttpStatus.CREATED, response.getStatusCode());
+    }
 
 }
diff --git a/fda-document-service/rest-service/src/test/java/at/tuwien/service/DocumentServiceIntegrationTest.java b/fda-document-service/rest-service/src/test/java/at/tuwien/service/DocumentServiceIntegrationTest.java
index 055fd45ca2538f514c3391c5263899d77c96645e..cdef81d0dc3c76705f8f6fba770e1291cd90874a 100644
--- a/fda-document-service/rest-service/src/test/java/at/tuwien/service/DocumentServiceIntegrationTest.java
+++ b/fda-document-service/rest-service/src/test/java/at/tuwien/service/DocumentServiceIntegrationTest.java
@@ -2,7 +2,7 @@ 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.api.document.record.RecordDto;
 import at.tuwien.exception.DraftRecordCreateException;
 import lombok.extern.log4j.Log4j2;
 import org.apache.http.auth.BasicUserPrincipal;
@@ -35,7 +35,7 @@ public class DocumentServiceIntegrationTest extends BaseUnitTest {
         /* mock */
 
         /* test */
-        final DraftDto response = documentService.create(request, principal);
+        final RecordDto response = documentService.create(request, principal);
         assertEquals(DOCUMENT_1_TITLE, response.getMetadata().getTitle());
     }
 
@@ -47,8 +47,8 @@ public class DocumentServiceIntegrationTest extends BaseUnitTest {
         /* mock */
 
         /* test */
-        final DraftDto document = documentService.create(request, principal);
-        final DraftDto response = documentService.reserveDoi(document.getId(), principal);
+        final RecordDto document = documentService.create(request, principal);
+        final RecordDto response = documentService.reserveDoi(document.getId(), principal);
         assertNotNull(response.getPids().getDoi());
     }
 
diff --git a/fda-document-service/rest-service/src/test/java/at/tuwien/service/FileServiceIntegrationTest.java b/fda-document-service/rest-service/src/test/java/at/tuwien/service/FileServiceIntegrationTest.java
index 91728896171d4d8f798c288f690daf5edc859388..b694b019aac679f968767d37c6bb716943a2802f 100644
--- a/fda-document-service/rest-service/src/test/java/at/tuwien/service/FileServiceIntegrationTest.java
+++ b/fda-document-service/rest-service/src/test/java/at/tuwien/service/FileServiceIntegrationTest.java
@@ -1,21 +1,31 @@
 package at.tuwien.service;
 
 import at.tuwien.BaseUnitTest;
-import at.tuwien.api.document.file.FileStartDto;
+import at.tuwien.api.document.file.FileDto;
 import at.tuwien.api.document.record.CreateDraftDto;
-import at.tuwien.api.document.record.DraftDto;
+import at.tuwien.api.document.record.RecordDto;
+import at.tuwien.exception.FileUploadException;
+import at.tuwien.exception.CommitFileUploadException;
 import at.tuwien.exception.DraftRecordCreateException;
 import lombok.extern.log4j.Log4j2;
+import org.apache.commons.io.FileUtils;
 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.mock.web.MockMultipartFile;
 import org.springframework.test.annotation.DirtiesContext;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.web.multipart.MultipartFile;
 
+import java.io.File;
+import java.io.IOException;
 import java.security.Principal;
 
+import static org.junit.jupiter.api.Assertions.*;
+
+
 @Log4j2
 @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
 @ExtendWith(SpringExtension.class)
@@ -29,15 +39,35 @@ public class FileServiceIntegrationTest extends BaseUnitTest {
     private FileService fileService;
 
     @Test
-    public void start_succeeds() throws DraftRecordCreateException {
+    public void upload_succeeds()
+            throws DraftRecordCreateException, IOException, CommitFileUploadException, FileUploadException {
+        final CreateDraftDto request = DOCUMENT_2_CREATE_DRAFT;
+        final Principal principal = new BasicUserPrincipal(USER_1_USERNAME);
+        final File mockFile = new File("src/test/resources/images/mock.png");
+
+        /* mock */
+        final MultipartFile file = new MockMultipartFile(mockFile.getName(), FileUtils.openInputStream(mockFile)
+                .readAllBytes());
+        final RecordDto document = documentService.create(request, principal);
+        assertFalse(document.getIsPublished());
+
+        /* test */
+        final FileDto response = fileService.uploadFile(document.getId(), file, principal);
+        assertEquals(file.getName(), response.getKey());
+    }
+    @Test
+    public void publish_succeeds()
+            throws DraftRecordCreateException {
         final CreateDraftDto request = DOCUMENT_1_CREATE_DRAFT;
         final Principal principal = new BasicUserPrincipal(USER_1_USERNAME);
 
         /* mock */
-        final DraftDto document = documentService.create(request, principal);
+        final RecordDto document = documentService.create(request, principal);
 
         /* test */
-        final FileStartDto response = fileService.start(document.getId(), principal);
+        final RecordDto response = documentService.publish(document.getId(), principal);
+        assertTrue(response.getIsPublished());
+        assertNotNull(response.getPids().getDoi());
     }
 
 }
diff --git a/fda-document-service/rest-service/src/test/resources/images/mock.png b/fda-document-service/rest-service/src/test/resources/images/mock.png
new file mode 100644
index 0000000000000000000000000000000000000000..4094aa6f22d95544339040f01f4f3d19f587d1d3
Binary files /dev/null and b/fda-document-service/rest-service/src/test/resources/images/mock.png differ
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
index e33f0dba4dddf90216af08dbb5ec98b184fbf6f6..4d819a17867603ab7f017a9f678f387cce38ef87 100644
--- 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
@@ -55,4 +55,4 @@ public class AuthTokenFilter extends OncePerRequestFilter {
         }
         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
index 006541ad8cd45351c455e1bf03b4c546acf3a6e8..776e4aa5d865bcfafa7768fb43c1b0f67fadb4a6 100644
--- 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
@@ -9,11 +9,21 @@ import org.springframework.web.util.DefaultUriBuilderFactory;
 @Configuration
 public class GatewayConfig {
 
+    @Value("${fda.gateway.endpoint}")
+    private String gatewayEndpoint;
+
     @Value("${fda.document.endpoint}")
     private String documentEndpoint;
 
     @Bean
-    public RestTemplate restTemplate() {
+    public RestTemplate gatewayRestTemplate() {
+        final RestTemplate restTemplate =  new RestTemplate();
+        restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(gatewayEndpoint));
+        return restTemplate;
+    }
+
+    @Bean
+    public RestTemplate documentRestTemplate() {
         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/WebSecurityConfig.java b/fda-document-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java
index 70dac68fcd138939eaa08a33a7789bd5830b369d..472089fc210e9f5abc231a766e173a7b14e18123 100644
--- 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
@@ -65,7 +65,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
         /* 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/**",
diff --git a/fda-document-service/services/src/main/java/at/tuwien/exception/CommitFileUploadException.java b/fda-document-service/services/src/main/java/at/tuwien/exception/CommitFileUploadException.java
new file mode 100644
index 0000000000000000000000000000000000000000..430f7bba544ef114e88e86279331d13b695ca48a
--- /dev/null
+++ b/fda-document-service/services/src/main/java/at/tuwien/exception/CommitFileUploadException.java
@@ -0,0 +1,21 @@
+package at.tuwien.exception;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseStatus(code = HttpStatus.CONFLICT)
+public class CommitFileUploadException extends Exception {
+
+    public CommitFileUploadException(String msg) {
+        super(msg);
+    }
+
+    public CommitFileUploadException(String msg, Throwable thr) {
+        super(msg, thr);
+    }
+
+    public CommitFileUploadException(Throwable thr) {
+        super(thr);
+    }
+
+}
diff --git a/fda-document-service/services/src/main/java/at/tuwien/exception/FileUploadException.java b/fda-document-service/services/src/main/java/at/tuwien/exception/FileUploadException.java
new file mode 100644
index 0000000000000000000000000000000000000000..590060826fb56e84a06df5d59c8828e336d130d3
--- /dev/null
+++ b/fda-document-service/services/src/main/java/at/tuwien/exception/FileUploadException.java
@@ -0,0 +1,21 @@
+package at.tuwien.exception;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseStatus(code = HttpStatus.FAILED_DEPENDENCY)
+public class FileUploadException extends Exception {
+
+    public FileUploadException(String msg) {
+        super(msg);
+    }
+
+    public FileUploadException(String msg, Throwable thr) {
+        super(msg, thr);
+    }
+
+    public FileUploadException(Throwable thr) {
+        super(thr);
+    }
+
+}
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
index fe6a27d6d509c7d224013b9a3f9a6a909436595b..36d86d6d02ad31e95ab64e8a3807d7aff637533f 100644
--- 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
@@ -1,18 +1,26 @@
 package at.tuwien.gateway;
 
-import at.tuwien.api.document.file.FileStartDto;
+import at.tuwien.api.document.file.FileDto;
 import at.tuwien.api.document.record.CreateDraftDto;
-import at.tuwien.api.document.record.DraftDto;
+import at.tuwien.api.document.record.RecordDto;
+import at.tuwien.exception.FileUploadException;
+import at.tuwien.exception.CommitFileUploadException;
 import at.tuwien.exception.DraftRecordCreateException;
+import org.springframework.web.multipart.MultipartFile;
 
 public interface DocumentGateway {
-    DraftDto createDraft(CreateDraftDto data, String token) throws DraftRecordCreateException;
+    RecordDto createDraft(CreateDraftDto data, String token) throws DraftRecordCreateException;
 
-    DraftDto reserveDraftDoi(String id, String token) throws DraftRecordCreateException;
+    RecordDto reserveDraftDoi(String id, String token) throws DraftRecordCreateException;
 
-    DraftDto findDraft(String id, String token) throws DraftRecordCreateException;
+    RecordDto findDraft(String id, String token) throws DraftRecordCreateException;
 
-    FileStartDto startUpload(String id, String token) throws DraftRecordCreateException;
+    RecordDto publishDraft(String id, String token) throws DraftRecordCreateException;
+
+    FileDto uploadFile(String id, MultipartFile file, String token)
+            throws DraftRecordCreateException, FileUploadException,
+            org.apache.tomcat.util.http.fileupload.FileUploadException,
+            CommitFileUploadException;
 
     void delete(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
index 56d691a6c825b473029c8f1dcd320c949cdcf177..549223342060b34913be4b0ab82a38e054838518 100644
--- 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
@@ -18,20 +18,20 @@ import org.springframework.web.client.RestTemplate;
 public class AuthenticationServiceGatewayImpl implements AuthenticationServiceGateway {
 
     private final UserMapper userMapper;
-    private final RestTemplate restTemplate;
+    private final RestTemplate gatewayRestTemplate;
 
     @Autowired
-    public AuthenticationServiceGatewayImpl(UserMapper userMapper, RestTemplate restTemplate) {
+    public AuthenticationServiceGatewayImpl(UserMapper userMapper, RestTemplate gatewayRestTemplate) {
         this.userMapper = userMapper;
-        this.restTemplate = restTemplate;
+        this.gatewayRestTemplate = gatewayRestTemplate;
     }
 
     @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);
+        final ResponseEntity<UserDto> response = gatewayRestTemplate.exchange("/api/auth", HttpMethod.PUT,
+                new HttpEntity<>(null, 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
index 318594ee12efef1f9f0d3fd6c9e2539181469770..bca9d5b863c9261e7cef4217925c331b9937b65f 100644
--- 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
@@ -1,36 +1,49 @@
 package at.tuwien.gateway.impl;
 
-import at.tuwien.api.document.file.FileStartDto;
+import at.tuwien.api.document.file.FileAnnounceDto;
+import at.tuwien.api.document.file.FileDto;
+import at.tuwien.api.document.file.FileKeyDto;
 import at.tuwien.api.document.record.CreateDraftDto;
-import at.tuwien.api.document.record.DraftDto;
+import at.tuwien.api.document.record.RecordDto;
+import at.tuwien.exception.FileUploadException;
+import at.tuwien.exception.CommitFileUploadException;
 import at.tuwien.exception.DraftRecordCreateException;
 import at.tuwien.gateway.DocumentGateway;
+import at.tuwien.mapper.DocumentMapper;
 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;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.List;
 
 @Slf4j
 @Component
 public class InvenioDocumentGatewayImpl implements DocumentGateway {
 
-    private RestTemplate restTemplate;
+    private final static String OCTET_STREAM = "application/octet-stream";
+
+    private final DocumentMapper documentMapper;
+    private final RestTemplate documentRestTemplate;
 
     @Autowired
-    public InvenioDocumentGatewayImpl(RestTemplate restTemplate) {
-        this.restTemplate = restTemplate;
+    public InvenioDocumentGatewayImpl(DocumentMapper documentMapper, RestTemplate documentRestTemplate) {
+        this.documentMapper = documentMapper;
+        this.documentRestTemplate = documentRestTemplate;
     }
 
     @Override
-    public DraftDto createDraft(CreateDraftDto data, String token) throws DraftRecordCreateException {
+    public RecordDto createDraft(CreateDraftDto data, String token) throws DraftRecordCreateException {
         log.trace("sending {}", data);
         final String url = "/api/records";
-        final ResponseEntity<DraftDto> response;
+        final ResponseEntity<RecordDto> response;
         try {
-            response = restTemplate.exchange(url, HttpMethod.POST,
-                    new HttpEntity<>(data, headers(token)), DraftDto.class);
+            response = documentRestTemplate.exchange(url, HttpMethod.POST,
+                    new HttpEntity<>(data, headers(token)), RecordDto.class);
         } catch (HttpClientErrorException.BadRequest e) {
             log.error("Failed to create draft record");
             throw new DraftRecordCreateException("Failed to create draft record", e);
@@ -39,12 +52,12 @@ public class InvenioDocumentGatewayImpl implements DocumentGateway {
     }
 
     @Override
-    public DraftDto reserveDraftDoi(String id, String token) throws DraftRecordCreateException {
+    public RecordDto reserveDraftDoi(String id, String token) throws DraftRecordCreateException {
         final String url = "/api/records/" + id + "/draft/pids/doi";
-        final ResponseEntity<DraftDto> response;
+        final ResponseEntity<RecordDto> response;
         try {
-            response = restTemplate.exchange(url, HttpMethod.POST,
-                    new HttpEntity<>(null, headers(token)), DraftDto.class);
+            response = documentRestTemplate.exchange(url, HttpMethod.POST,
+                    new HttpEntity<>(null, headers(token)), RecordDto.class);
         } catch (HttpClientErrorException.BadRequest e) {
             log.error("Failed to reserve draft doi");
             throw new DraftRecordCreateException("Failed to reserve draft doi", e);
@@ -53,12 +66,12 @@ public class InvenioDocumentGatewayImpl implements DocumentGateway {
     }
 
     @Override
-    public DraftDto findDraft(String id, String token) throws DraftRecordCreateException {
+    public RecordDto findDraft(String id, String token) throws DraftRecordCreateException {
         final String url = "/api/records/" + id + "/draft";
-        final ResponseEntity<DraftDto> response;
+        final ResponseEntity<RecordDto> response;
         try {
-            response = restTemplate.exchange(url, HttpMethod.GET,
-                    new HttpEntity<>(null, headers(token)), DraftDto.class);
+            response = documentRestTemplate.exchange(url, HttpMethod.GET,
+                    new HttpEntity<>(null, headers(token)), RecordDto.class);
         } catch (HttpClientErrorException.BadRequest e) {
             log.error("Failed to find draft record");
             throw new DraftRecordCreateException("Failed to create find record", e);
@@ -67,24 +80,76 @@ public class InvenioDocumentGatewayImpl implements DocumentGateway {
     }
 
     @Override
-    public FileStartDto startUpload(String id, String token) throws DraftRecordCreateException {
-        final String url = "/api/records/" + id + "/draft/files";
-        final ResponseEntity<FileStartDto> response;
+    public RecordDto publishDraft(String id, String token) throws DraftRecordCreateException {
+        final String url = "/api/records/" + id + "/draft/actions/publish";
+        final ResponseEntity<RecordDto> response;
         try {
-            response = restTemplate.exchange(url, HttpMethod.POST,
-                    new HttpEntity<>(null, headers(token)), FileStartDto.class);
+            response = documentRestTemplate.exchange(url, HttpMethod.POST,
+                    new HttpEntity<>(null, headers(token)), RecordDto.class);
         } catch (HttpClientErrorException.BadRequest e) {
-            log.error("Failed to start draft files");
-            throw new DraftRecordCreateException("Failed to start draft files", e);
+            log.error("Failed to publish draft record");
+            throw new DraftRecordCreateException("Failed to publish find record", e);
         }
         return response.getBody();
     }
 
+    @Override
+    public FileDto uploadFile(String id, MultipartFile file, String token)
+            throws FileUploadException {
+        /* announce */
+        final String url1 = "/api/records/" + id + "/draft/files";
+        final List<FileKeyDto> files = List.of(documentMapper.stringToFileKeyDto(file.getName()));
+        final ResponseEntity<FileAnnounceDto> response1;
+        try {
+            response1 = documentRestTemplate.exchange(url1, HttpMethod.POST,
+                    new HttpEntity<>(files, headers(token)), FileAnnounceDto.class);
+        } catch (HttpClientErrorException.BadRequest e) {
+            log.error("Failed to announce draft file");
+            throw new FileUploadException("Failed to announce draft file", e);
+        }
+        if (response1.getStatusCode() != HttpStatus.CREATED) {
+            log.error("Failed to announce file upload");
+            throw new FileUploadException("Failed to announce file upload");
+        }
+        /* upload */
+        final String url2 = "/api/records/" + id + "/draft/files/" + file.getName() + "/content";
+        final ResponseEntity<Void> response2;
+        try {
+            response2 = documentRestTemplate.exchange(url2, HttpMethod.PUT,
+                    new HttpEntity<>(file.getBytes(), headers(token, OCTET_STREAM)), Void.class);
+        } catch (HttpClientErrorException.BadRequest e) {
+            log.error("Failed to upload draft file");
+            throw new FileUploadException("Failed to upload draft file", e);
+        } catch (IOException e) {
+            log.error("Failed to get draft file bytes");
+            throw new FileUploadException("Failed to get draft file bytes", e);
+        }
+        if (response2.getStatusCode() != HttpStatus.OK) {
+            log.error("Failed to upload file");
+            throw new FileUploadException("Failed to upload file");
+        }
+        /* commit */
+        final String url3 = "/api/records/" + id + "/draft/files/" + file.getName() + "/commit";
+        final ResponseEntity<FileDto> response3;
+        try {
+            response3 = documentRestTemplate.exchange(url3, HttpMethod.POST,
+                    new HttpEntity<>(null, headers(token)), FileDto.class);
+        } catch (HttpClientErrorException.BadRequest e) {
+            log.error("Failed to commit draft file");
+            throw new FileUploadException("Failed to commit draft file", e);
+        }
+        if (response3.getStatusCode() != HttpStatus.OK) {
+            log.error("Failed to commit file");
+            throw new FileUploadException("Failed to commit file");
+        }
+        return response3.getBody();
+    }
+
     @Override
     public void delete(String id, String token) throws DraftRecordCreateException {
         final String url = "/api/records" + id + "/draft";
         try {
-            restTemplate.exchange(url, HttpMethod.DELETE,
+            documentRestTemplate.exchange(url, HttpMethod.DELETE,
                     new HttpEntity<>(null, headers(token)), Void.class);
         } catch (HttpClientErrorException.BadRequest e) {
             log.error("Failed to delete draft record");
@@ -99,9 +164,20 @@ public class InvenioDocumentGatewayImpl implements DocumentGateway {
      * @return The headers.
      */
     private HttpHeaders headers(String token) {
+        return headers(token, "application/json");
+    }
+
+    /**
+     * Prepares the headers for all requests to authorize with the bearer token and content type.
+     *
+     * @param token       The token.
+     * @param contentType The content type.
+     * @return The headers.
+     */
+    private HttpHeaders headers(String token, String contentType) {
         final HttpHeaders headers = new HttpHeaders();
         headers.add("Authorization", "Bearer " + token);
-        headers.add("Content-Type", "application/json");
+        headers.add("Content-Type", contentType);
         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
index 0132073b6294cdb9be25a589d4d253fd06ed5b6c..2457da7cecbb72312d72293e54fd0720e750e75e 100644
--- 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
@@ -1,10 +1,16 @@
 package at.tuwien.mapper;
 
+import at.tuwien.api.document.file.FileKeyDto;
 import org.mapstruct.*;
 
 
 @Mapper(componentModel = "spring")
 public interface DocumentMapper {
 
+    default FileKeyDto stringToFileKeyDto(String data) {
+        return FileKeyDto.builder()
+                .key(data)
+                .build();
+    }
 
 }
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
index 5d102b335c226e599fb92bdbc44f7db856240fe3..182feb2d5b0d627ce42bbfca39ecda83341235ce 100644
--- 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
@@ -1,18 +1,20 @@
 package at.tuwien.service;
 
 import at.tuwien.api.document.record.CreateDraftDto;
-import at.tuwien.api.document.record.DraftDto;
+import at.tuwien.api.document.record.RecordDto;
 import at.tuwien.exception.DraftRecordCreateException;
 
 import java.security.Principal;
 
 public interface DocumentService {
 
-    DraftDto findById(String id, Principal principal) throws DraftRecordCreateException;
+    RecordDto findById(String id, Principal principal) throws DraftRecordCreateException;
 
-    DraftDto create(CreateDraftDto data, Principal principal) throws DraftRecordCreateException;
+    RecordDto create(CreateDraftDto data, Principal principal) throws DraftRecordCreateException;
 
-    DraftDto reserveDoi(String id, Principal principal) throws DraftRecordCreateException;
+    RecordDto publish(String id, Principal principal) throws DraftRecordCreateException;
+
+    RecordDto reserveDoi(String id, Principal principal) throws DraftRecordCreateException;
 
     void delete(String id, Principal principal) throws DraftRecordCreateException;
 }
diff --git a/fda-document-service/services/src/main/java/at/tuwien/service/FileService.java b/fda-document-service/services/src/main/java/at/tuwien/service/FileService.java
index 5113be20f9cc2700e4c128785ad05020b39c1c2d..67fb8932b57eac8afefa48b5331585b5b2460e8e 100644
--- a/fda-document-service/services/src/main/java/at/tuwien/service/FileService.java
+++ b/fda-document-service/services/src/main/java/at/tuwien/service/FileService.java
@@ -1,11 +1,17 @@
 package at.tuwien.service;
 
 
-import at.tuwien.api.document.file.FileStartDto;
+import at.tuwien.api.document.file.FileDto;
+import at.tuwien.exception.FileUploadException;
+import at.tuwien.exception.CommitFileUploadException;
 import at.tuwien.exception.DraftRecordCreateException;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.security.Principal;
 
 public interface FileService {
-    FileStartDto start(String id, Principal principal) throws DraftRecordCreateException;
+
+    FileDto uploadFile(String id, MultipartFile file, Principal principal)
+            throws DraftRecordCreateException, CommitFileUploadException, FileUploadException,
+            org.apache.tomcat.util.http.fileupload.FileUploadException;
 }
diff --git a/fda-document-service/services/src/main/java/at/tuwien/service/impl/InvenioDraftServiceImpl.java b/fda-document-service/services/src/main/java/at/tuwien/service/impl/InvenioDraftServiceImpl.java
index 456fd6b540ee01387bccec7ee51a07bbde66b867..06c038521a7b2224b12de6f4811958deb80b729f 100644
--- a/fda-document-service/services/src/main/java/at/tuwien/service/impl/InvenioDraftServiceImpl.java
+++ b/fda-document-service/services/src/main/java/at/tuwien/service/impl/InvenioDraftServiceImpl.java
@@ -1,7 +1,7 @@
 package at.tuwien.service.impl;
 
 import at.tuwien.api.document.record.CreateDraftDto;
-import at.tuwien.api.document.record.DraftDto;
+import at.tuwien.api.document.record.RecordDto;
 import at.tuwien.config.InvenioConfig;
 import at.tuwien.exception.DraftRecordCreateException;
 import at.tuwien.gateway.DocumentGateway;
@@ -26,27 +26,37 @@ public class InvenioDraftServiceImpl implements DocumentService {
     }
 
     @Override
-    public DraftDto findById(String id, Principal principal) throws DraftRecordCreateException {
+    public RecordDto 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 {
+    public RecordDto create(CreateDraftDto data, Principal principal) throws DraftRecordCreateException {
         /* get token */
         /* remote */
-        final DraftDto document = documentGateway.createDraft(data, invenioConfig.getDebugToken());
+        final RecordDto 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 {
+    public RecordDto publish(String id, Principal principal) throws DraftRecordCreateException {
         /* get token */
         /* remote */
-        final DraftDto document = documentGateway.reserveDraftDoi(id, invenioConfig.getDebugToken());
+        final RecordDto document = documentGateway.publishDraft(id, invenioConfig.getDebugToken());
+        log.info("Published draft record with id {}", document.getId());
+        log.debug("published draft record {}", document);
+        return document;
+    }
+
+    @Override
+    public RecordDto reserveDoi(String id, Principal principal) throws DraftRecordCreateException {
+        /* get token */
+        /* remote */
+        final RecordDto 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-document-service/services/src/main/java/at/tuwien/service/impl/InvenioFileServiceImpl.java b/fda-document-service/services/src/main/java/at/tuwien/service/impl/InvenioFileServiceImpl.java
index 459454f3462f78715d1a5a89d13696e10e2aefee..4110d0784614f364a6a529065b285349b4a00be9 100644
--- a/fda-document-service/services/src/main/java/at/tuwien/service/impl/InvenioFileServiceImpl.java
+++ b/fda-document-service/services/src/main/java/at/tuwien/service/impl/InvenioFileServiceImpl.java
@@ -1,13 +1,16 @@
 package at.tuwien.service.impl;
 
-import at.tuwien.api.document.file.FileStartDto;
+import at.tuwien.api.document.file.FileDto;
 import at.tuwien.config.InvenioConfig;
+import at.tuwien.exception.FileUploadException;
+import at.tuwien.exception.CommitFileUploadException;
 import at.tuwien.exception.DraftRecordCreateException;
 import at.tuwien.gateway.DocumentGateway;
 import at.tuwien.service.FileService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.security.Principal;
 
@@ -25,12 +28,14 @@ public class InvenioFileServiceImpl implements FileService {
     }
 
     @Override
-    public FileStartDto start(String id, Principal principal) throws DraftRecordCreateException {
+    public FileDto uploadFile(String id, MultipartFile file, Principal principal)
+            throws DraftRecordCreateException, CommitFileUploadException, FileUploadException,
+            org.apache.tomcat.util.http.fileupload.FileUploadException {
         /* get token */
         /* remote */
-        final FileStartDto document = documentGateway.startUpload(id, invenioConfig.getDebugToken());
-        log.info("Started draft files with id {}", id);
-        log.debug("started draft files {}", document);
+        final FileDto document = documentGateway.uploadFile(id, file, invenioConfig.getDebugToken());
+        log.info("Deposited draft file content for record with id {}", id);
+        log.debug("Deposited draft file content for record {}", document);
         return document;
     }
 
diff --git a/fda-gateway-service/gateway/src/main/java/at/tuwien/gatewayservice/config/GatewayConfig.java b/fda-gateway-service/gateway/src/main/java/at/tuwien/gatewayservice/config/GatewayConfig.java
index 040bbb0e969ed5e8276618238d70cf0726d33a24..27a3863e809929f10fe5550b139a51b05f4e2ba2 100644
--- a/fda-gateway-service/gateway/src/main/java/at/tuwien/gatewayservice/config/GatewayConfig.java
+++ b/fda-gateway-service/gateway/src/main/java/at/tuwien/gatewayservice/config/GatewayConfig.java
@@ -56,6 +56,11 @@ public class GatewayConfig {
                         .method("POST", "GET", "PUT", "DELETE")
                         .and()
                         .uri("lb://fda-units-service"))
+                .route("fda-document-service", r -> r.path("/api/document/**")
+                        .and()
+                        .method("POST", "GET", "PUT", "DELETE")
+                        .and()
+                        .uri("lb://fda-document-service"))
                 .build();
 
     }
diff --git a/fda-identifier-service/rest-service/src/main/java/at/tuwien/FdaIdentifierServiceApplication.java b/fda-identifier-service/rest-service/src/main/java/at/tuwien/FdaIdentifierServiceApplication.java
index 185a41efc0b3900e7aa9b47f188e8cb30bc4d170..56712b0f03861daf0c381a949b6d3252b2843c41 100644
--- a/fda-identifier-service/rest-service/src/main/java/at/tuwien/FdaIdentifierServiceApplication.java
+++ b/fda-identifier-service/rest-service/src/main/java/at/tuwien/FdaIdentifierServiceApplication.java
@@ -8,7 +8,6 @@ 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
diff --git a/fda-identifier-service/rest-service/src/main/resources/application.yml b/fda-identifier-service/rest-service/src/main/resources/application.yml
index 11335fa111792cbd07a41a804b21e496d3cfec90..e71ce69b3fe660d786ba6dab44a19407bd1b2b22 100644
--- a/fda-identifier-service/rest-service/src/main/resources/application.yml
+++ b/fda-identifier-service/rest-service/src/main/resources/application.yml
@@ -22,6 +22,7 @@ logging:
   level:
     root: warn
     at.tuwien.: debug
+    at.tuwien.gateway.: trace
     org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug
 eureka:
   instance.hostname: fda-identifier-service
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/file/FileAnnounceDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/file/FileAnnounceDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..c2941ccdeca9d5556ca203eecf5b99a2b5210733
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/file/FileAnnounceDto.java
@@ -0,0 +1,37 @@
+
+package at.tuwien.api.document.file;
+
+import at.tuwien.api.document.links.LinksDto;
+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.util.List;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class FileAnnounceDto {
+
+    @JsonProperty("default_preview")
+    @Parameter(name = "file name")
+    private String defaultPreview;
+
+    @NotNull
+    @Parameter(name = "file enabled")
+    private Boolean enabled;
+
+    @NotNull
+    @Parameter(name = "file entries")
+    private List<FileEntryDto> entries;
+
+    @Parameter(name = "file links")
+    private LinksDto links;
+
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/file/FileDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/file/FileDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..63f820e3724f03190b932614a119b96277cfd7f0
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/file/FileDto.java
@@ -0,0 +1,72 @@
+package at.tuwien.api.document.file;
+
+import at.tuwien.api.document.links.LinksDto;
+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.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.time.Instant;
+
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class FileDto {
+
+    @NotBlank
+    @JsonProperty("bucket_id")
+    @Parameter(name = "bucket id", description = "Bucket id.")
+    private String bucketId;
+
+    @NotBlank
+    @Parameter(name = "file checksum", description = "File checksum.", example = "md5:ef8fcf1f046bb24f1db1f1a376ddbfbb")
+    private String checksum;
+
+    @NotNull
+    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX", timezone = "UTC+2")
+    @Parameter(name = "file creation timestamp")
+    private Instant created;
+
+    @NotNull
+    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX", timezone = "UTC+2")
+    @Parameter(name = "file updated timestamp")
+    private Instant updated;
+
+    @NotBlank
+    @JsonProperty("file_id")
+    @Parameter(name = "file id")
+    private String fileId;
+
+    @NotBlank
+    @Parameter(name = "file key", example = "mock.png")
+    private String key;
+
+    @NotNull
+    @Parameter(name = "file links")
+    private LinksDto links;
+
+    @Parameter(name = "file mimetype")
+    private String mimetype;
+
+    @Parameter(name = "file size")
+    private Long size;
+
+    @Parameter(name = "file status")
+    private String status;
+
+    @JsonProperty("storage_class")
+    @Parameter(name = "file storage class", example = "S")
+    private String storageClass;
+
+    @JsonProperty("version_id")
+    @Parameter(name = "file version id")
+    private String versionId;
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/file/FileEntryDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/file/FileEntryDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..d4c7909d5a1d0f075ca474c60610a2b1dfbe1cea
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/file/FileEntryDto.java
@@ -0,0 +1,43 @@
+
+package at.tuwien.api.document.file;
+
+import at.tuwien.api.document.links.LinksDto;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.v3.oas.annotations.Parameter;
+import lombok.*;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.time.Instant;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class FileEntryDto {
+
+    @NotBlank
+    @Parameter(name = "file name", description = "Name of the file.")
+    private String key;
+
+    @NotNull
+    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX", timezone = "UTC+2")
+    @Parameter(name = "file updated")
+    private Instant updated;
+
+    @NotNull
+    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX", timezone = "UTC+2")
+    @Parameter(name = "file created")
+    private Instant created;
+
+    @Parameter(name = "file status")
+    private String status;
+
+    @Parameter(name = "file links")
+    private LinksDto links;
+
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/document/file/FileKeyDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/file/FileKeyDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..79c7f3d7b7d1a6d620edd505543f27fd3c1dc9c0
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/document/file/FileKeyDto.java
@@ -0,0 +1,23 @@
+
+package at.tuwien.api.document.file;
+
+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 FileKeyDto {
+
+    @NotBlank
+    @Parameter(name = "file name", description = "Name of the file.", example = "mock.png")
+    private String key;
+
+}
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/RecordDto.java
similarity index 98%
rename from fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/DraftDto.java
rename to fda-metadata-db/api/src/main/java/at/tuwien/api/document/record/RecordDto.java
index d754f22fce839fe952e855fff31903dc0194dc27..0f41c523bb4fa2a31dc9446681bc3c5e372d33c1 100644
--- 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/RecordDto.java
@@ -18,7 +18,7 @@ import java.time.Instant;
 @AllArgsConstructor
 @NoArgsConstructor
 @JsonInclude(JsonInclude.Include.NON_NULL)
-public class DraftDto {
+public class RecordDto {
 
     @NotNull(message = "access is required")
     @Parameter(name = "access")
diff --git a/fda-ui/server-middleware/index.js b/fda-ui/server-middleware/index.js
index b74dab08920ad0f14cc1b38e15ee3b7216b90361..819f649f24a9ac7eb00f1d5a9a1b95e9475c7b19 100644
--- a/fda-ui/server-middleware/index.js
+++ b/fda-ui/server-middleware/index.js
@@ -25,6 +25,7 @@ app.post('/table_from_csv', upload.single('file'), async (req, res) => {
 
   // send path to analyse service
   let analysis
+  let json
   try {
     const analyseUrl = `${process.env.API}/api/analyse/determinedt`
     analysis = await fetch(analyseUrl, {
@@ -35,9 +36,8 @@ app.post('/table_from_csv', upload.single('file'), async (req, res) => {
       console.error('data type determination failed', error)
       throw error
     })
-    const json = await analysis.json()
-    analysis = JSON.parse(json)
-    if (!analysis.columns) {
+    json = await analysis.json()
+    if (!json.columns) {
       return res.json({ success: false, message: 'Columns array missing' })
     }
   } catch (error) {
@@ -47,7 +47,7 @@ app.post('/table_from_csv', upload.single('file'), async (req, res) => {
 
   // map messytables / CoMi's `determine_dt` column types to ours
   // e.g. "Integer" -> "NUMBER"
-  let entries = Object.entries(analysis.columns)
+  let entries = Object.entries(json.columns)
   entries = entries.map(([k, v]) => {
     if (colTypeMap[v]) {
       v = colTypeMap[v]