diff --git a/nomad/api/common.py b/nomad/api/common.py
new file mode 100644
index 0000000000000000000000000000000000000000..6ef240fbd8332d40d06f9e35a7e31acdb4d96d24
--- /dev/null
+++ b/nomad/api/common.py
@@ -0,0 +1,52 @@
+# Copyright 2018 Markus Scheidgen
+#
+# Licensed 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
+#
+#   http://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.
+
+"""
+Common data, variables, decorators, models used throughout the API.
+"""
+
+from flask_restplus import fields
+
+from .app import api
+
+
+pagination_model = api.model('Pagination', {
+    'total': fields.Integer,
+    'page': fields.Integer,
+    'per_page': fields.Integer,
+})
+""" Model used in responsed with pagination. """
+
+
+pagination_request_parser = api.parser()
+""" Parser used for requests with pagination. """
+
+pagination_request_parser.add_argument(
+    'page', type=int, help='The page, starting with 1.', location='args')
+pagination_request_parser.add_argument(
+    'per_page', type=int, help='Desired calcs per page.', location='args')
+pagination_request_parser.add_argument(
+    'order_by', type=str, help='The field to sort by.', location='args')
+
+
+def calc_route(ns, prefix: str = ''):
+    """ A resource decorator for /<upload>/<calc> based routes. """
+    def decorator(func):
+        ns.route('%s/<string:upload_hash>/<string:calc_hash>' % prefix)(
+            api.doc(params={
+                'upload_hash': 'The unique hash for the requested upload.',
+                'path': 'The path to a file or directory.'
+            })(func)
+        )
+    return decorator
diff --git a/nomad/api/repo.py b/nomad/api/repo.py
new file mode 100644
index 0000000000000000000000000000000000000000..79d096c0fac8a7bc5454fcce8732c9e120ecfc4f
--- /dev/null
+++ b/nomad/api/repo.py
@@ -0,0 +1,108 @@
+# Copyright 2018 Markus Scheidgen
+#
+# Licensed 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
+#
+#   http://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.
+
+"""
+The repository API of the nomad@FAIRDI APIs. Currently allows to resolve repository
+meta-data.
+"""
+
+from elasticsearch.exceptions import NotFoundError
+from flask import g, request
+from flask_restplus import Resource, abort, fields
+
+from nomad.repo import RepoCalc
+
+from .app import api
+from .auth import login_if_available
+from .common import pagination_model, pagination_request_parser, calc_route
+
+ns = api.namespace('repo', description='Access repository metadata, edit user metadata.')
+
+
+@calc_route(ns)
+class RepoCalcResource(Resource):
+    @api.response(404, 'The upload or calculation does not exist')
+    @api.response(200, 'Metadata send')
+    def get(self, upload_hash, calc_hash):
+        """
+        Get calculation metadata in repository form.
+
+        Repository metadata only entails the quanties shown in the repository.
+        This is basically the elastic search index entry for the
+        requested calculations. Calcs are references via *upload_hash*, *calc_hash*
+        pairs.
+        """
+        try:
+            return RepoCalc.get(id='%s/%s' % (upload_hash, calc_hash)).json_dict, 200
+        except NotFoundError:
+            abort(404, message='There is no calculation for %s/%s' % (upload_hash, calc_hash))
+        except Exception as e:
+            abort(500, message=str(e))
+
+
+repo_calcs_model = api.model('RepoCalculations', {
+    'pagination': fields.Nested(pagination_model),
+    'results': fields.List(fields.Raw)
+})
+
+repo_request_parser = pagination_request_parser.copy()
+repo_request_parser.add_argument(
+    'owner', type=str,
+    help='Specify which calcs to return: ``all``, ``user``, ``staging``, default is ``all``')
+
+
+@ns.route('/')
+class RepoCalcsResource(Resource):
+    @api.response(400, 'Invalid requests, e.g. wrong owner type')
+    @api.expect(repo_request_parser, validate=True)
+    @api.marshal_with(repo_calcs_model, skip_none=True, code=200, description='Metadata send')
+    @login_if_available
+    def get(self):
+        """
+        Get *'all'* calculations in repository from, paginated.
+        """
+        page = int(request.args.get('page', 1))
+        per_page = int(request.args.get('per_page', 10))
+        owner = request.args.get('owner', 'all')
+
+        try:
+            assert page >= 1
+            assert per_page > 0
+        except AssertionError:
+            abort(400, message='invalid pagination')
+
+        if owner == 'all':
+            search = RepoCalc.search().query('match_all')
+        elif owner == 'user':
+            if g.user is None:
+                abort(401, message='Authentication required for owner value user.')
+            search = RepoCalc.search().query('match_all')
+            search = search.filter('term', user_id=str(g.user.user_id))
+        elif owner == 'staging':
+            if g.user is None:
+                abort(401, message='Authentication required for owner value user.')
+            search = RepoCalc.search().query('match_all')
+            search = search.filter('term', user_id=str(g.user.user_id)).filter('term', staging=True)
+        else:
+            abort(400, message='Invalid owner value. Valid values are all|user|staging, default is all')
+
+        search = search[(page - 1) * per_page: page * per_page]
+        return {
+            'pagination': {
+                'total': search.count(),
+                'page': page,
+                'per_page': per_page
+            },
+            'results': [result.json_dict for result in search]
+        }, 200