diff --git a/spec/headers_test.js b/spec/headers_test.js
new file mode 100644
index 0000000000000000000000000000000000000000..efe76447e82cff70e624d96b4e55513a6c397fbb
--- /dev/null
+++ b/spec/headers_test.js
@@ -0,0 +1,63 @@
+import { describe, it, expect, beforeAll, afterAll, beforeEach, afterEach } from '@jest/globals'
+import mockfs from 'mock-fs'
+import request from 'supertest'
+import { createApp } from '../src/createApp'
+import { createMockServer, generateSimpleViteManifest, getRandomPort } from './util.js'
+
+describe('Responses contain custom headers', () => {
+  let app
+  let mockserver
+  const port = getRandomPort()
+
+  beforeAll(() => {
+    mockfs({
+      './config/manifests': {
+        'urls.yaml': `manifests:
+          - http://localhost:${port}/api/manifest.json`
+      }
+    })
+    app = createApp()
+  })
+
+  afterAll(() => {
+    mockfs.restore()
+  })
+
+  beforeEach(async () => {
+    mockserver = await createMockServer({ port })
+    mockserver.respondWith({
+      '/api/manifest.json': generateSimpleViteManifest({
+        'example.js': {},
+        'main.css': {},
+        'index.html': {
+          file: 'index.html.js',
+          isEntry: true,
+          imports: ['example.js'],
+          css: ['main.css']
+        }
+      }),
+      '/example.js': (req, res) => res.setHeader('content-type', 'application/javascript').status(200).send('this is example'),
+      '/index.html.js': (req, res) => res.setHeader('content-type', 'application/javascript').status(200).send('this is index.html.js'),
+      '/main.css': (req, res) => res.setHeader('content-type', 'text/css').status(200).send('.foo { color: #000; }'),
+      '/index.html': (req, res) => res.setHeader('content-type', 'text/html').status(200).send('<html><head></head><body>it\'s me</body></html>')
+    })
+    await request(app).get('/ready')
+  })
+
+  afterEach(() => {
+    mockserver.close()
+    process.env.CACHE_TTL = 30000
+  })
+
+  it('index.html has version', async () => {
+    const response = await request(app).get('/index.html')
+    expect(response.statusCode).toBe(200)
+    expect(response.headers.version).toMatch(/\d*\.3220550168/)
+  })
+
+  it('javascript file contains dependencies', async () => {
+    const response = await request(app).get('/index.html.js')
+    expect(response.statusCode).toBe(200)
+    expect(response.headers.dependencies).toEqual('example.js,main.css')
+  })
+})
diff --git a/src/createApp.js b/src/createApp.js
index f14a68a0031cfa4fad1273a53397e3f26337d0be..44066101ef8fad489dbbc8edabb7b8cafd27042a 100644
--- a/src/createApp.js
+++ b/src/createApp.js
@@ -18,7 +18,7 @@ import promBundle from 'express-prom-bundle'
 import swaggerUi from 'swagger-ui-express'
 import yaml from 'js-yaml'
 import fs from 'fs'
-import { getDependencies, getOxManifests } from './manifests.js'
+import { getDependencies, getOxManifests, getVersion } from './manifests.js'
 import { fileCache } from './files.js'
 
 const ignorePaths = ['/ready', '/healthy']
@@ -62,6 +62,12 @@ export function createApp () {
   app.use('/swagger.json', (req, res) => res.json(swaggerDocument))
   app.timeout = 30000
 
+  app.use(async (req, res, next) => {
+    const version = await getVersion()
+    if (version) res.setHeader('version', version)
+    next()
+  })
+
   app.get('/manifests', async (req, res, next) => {
     try {
       res.json(await getOxManifests())
@@ -86,14 +92,28 @@ export function createApp () {
 
   app.use(async (req, res, next) => {
     const { 'content-type': contentType, content } = fileCache.get(req.path)
-    if (content) return res.setHeader('content-type', contentType).status(200).send(content)
+    if (content) {
+      const allDependencies = await getDependencies()
+      const dependencies = allDependencies[req.path.substr(1)] || []
+      return res
+        .setHeader('content-type', contentType)
+        .setHeader('dependencies', dependencies.join(','))
+        .status(200).send(content)
+    }
     next()
   })
 
   app.use(async (req, res, next) => {
     try {
       const { 'content-type': contentType, content } = await fileCache.fetchAndStore(req.path)
-      if (content) return res.setHeader('content-type', contentType).status(200).send(content)
+      if (content) {
+        const allDependencies = await getDependencies()
+        const dependencies = allDependencies[req.path.substr(1)] || []
+        return res
+          .setHeader('content-type', contentType)
+          .setHeader('dependencies', dependencies.join(','))
+          .status(200).send(content)
+      }
     } catch (e) {}
     next()
   })
diff --git a/src/files.js b/src/files.js
index 46ceb809ddca2c31227512f29cb05638675c95e9..2ae2bb511e49879f752ae0f45a55b40d459f83a5 100644
--- a/src/files.js
+++ b/src/files.js
@@ -4,7 +4,7 @@ import { config } from './config.js'
 
 async function fetchData (path, baseUrl) {
   const response = await fetch(new URL(path, baseUrl))
-  if (!response.ok) throw new Error('Error fetching file')
+  if (!response.ok) throw new Error(`Error fetching file: ${path}`)
   const content = await response.buffer()
   const sha256Sum = crypto.createHash('sha256').update(content).digest('base64')
   return [path, {
diff --git a/src/manifests.js b/src/manifests.js
index a043e2786f67ce4a784793c892433f574d0a6546..3660508715bb08a0d9f8321e90a5fc1b205e301a 100644
--- a/src/manifests.js
+++ b/src/manifests.js
@@ -3,6 +3,7 @@ import path from 'path'
 import { URL } from 'url'
 import { fileCache } from './files.js'
 import { config } from './config.js'
+import { hash } from './util.js'
 
 export const loadViteManifests = (() => {
   let cache
@@ -104,3 +105,20 @@ export const getDependencies = (() => {
     return depCache
   }
 })()
+
+export const getVersion = (() => {
+  let prevViteManifest
+  let version
+  let versionString
+  return async function getVersion () {
+    const viteManifest = await loadViteManifests()
+    if (viteManifest !== prevViteManifest) {
+      const newVersion = hash(viteManifest)
+      if (newVersion !== version) {
+        versionString = `${+new Date()}.${newVersion}`
+        version = newVersion
+      }
+    }
+    return versionString
+  }
+})()
diff --git a/src/swagger.yaml b/src/swagger.yaml
index 0765cbfb1a849a9dcc98c02e6f3546a05904e070..aecf47a0d23024df40f0ae124faeaa0f12db7503 100644
--- a/src/swagger.yaml
+++ b/src/swagger.yaml
@@ -1,15 +1,34 @@
 openapi: 3.0.1
+tags:
+  - name: code loading
+servers:
+  - http://localhost:3000/
 info:
   title: Manifest Service
   version: 1.0.0
   description: Micro service that collects manifest files from different services and merge them into a single file
+  contact:
+    email: ui-team@open-xchange.com
 paths:
   /manifests:
     get:
+      operationId: manifests_get
+      tags:
+        - code loading
       summary: App Suite UI compatible version of manifests data
+      description: |
+        Manifest data prepared for consumption by App Suite UI. The data
+        can be used to determine the timing when to load certain files
+        from the server and depending on the users configuration also if
+        the files should be loaded at all.
       responses:
         '200':
           description: manifests data in JSON format
+          headers:
+            version:
+              schema:
+                type: string
+              description: The version of the manifest files
           content:
             application/json:
               schema:
@@ -43,10 +62,20 @@ paths:
                       example: '!smartphone'
   /dependencies:
     get:
+      operationId: dependencies_get
+      tags:
+        - code loading
       summary: Mapping of all files to all of its dependencies
+      description: |
+        The data can be used to construct a dependency tree for any given file of a project.
       responses:
         '200':
           description: dependency information for all files of the manifest
+          headers:
+            version:
+              schema:
+                type: string
+              description: The version of the manifest files
           content:
             application/json:
               schema:
diff --git a/src/util.js b/src/util.js
new file mode 100644
index 0000000000000000000000000000000000000000..0229cba7f435a4cd3554dacc1452e07a9b78ef48
--- /dev/null
+++ b/src/util.js
@@ -0,0 +1,16 @@
+// totaly awesome hash function. Do not use this for encryption (crypto.subtle.digest etc would be overkill for this)
+export function hash (array) {
+  const string = array.toString()
+  if (!string.length) throw new Error('TypeError: Unexpected data to calculate hash from')
+
+  let hash = 0
+  let char
+
+  for (let i = 0; i < string.length; i++) {
+    char = string.charCodeAt(i)
+    hash = ((hash << 5) - hash) + char
+    hash |= 0
+  }
+
+  return new Uint32Array([hash]).toString()
+}