diff --git a/app/fetch_event.ts b/app/fetch_event.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cd50265c88adbb5f895ee96933a93dc89caaa6cb
--- /dev/null
+++ b/app/fetch_event.ts
@@ -0,0 +1,73 @@
+import { HoliEvent } from './fetch_events.ts'
+import { logger } from './logging.ts'
+import { Activity } from './providers/jasd/appapi.dto.types.ts'
+import NotFound = Deno.errors.NotFound
+
+const APP_API_BASE_URL = 'https://gemeinschaftswerk-nachhaltigkeit.de/app/api/v1'
+const APP_FILES_BASE_URL = 'https://gemeinschaftswerk-nachhaltigkeit.de/app/api/v1/files'
+
+export type HoliEventResponse = {
+  data: HoliEvent
+}
+
+export type FetchEventInput = {
+  id: string
+}
+
+export const toHoliEvent = (activity: Activity): HoliEvent | null => {
+  if (activity.period.permanent) return null
+
+  return {
+    id: activity.id.toString(),
+    title: activity.name,
+    organisationName: activity.organisation.name,
+    startDate: activity.period.start,
+    endDate: activity.period.end,
+    location: {
+      city: activity.location.address.city,
+      street: activity.location.address.street,
+      streetNo: activity.location.address.streetNo,
+      zipCode: activity.location.address.zipCode,
+    },
+    isRemote: activity.location.online,
+    // todo gregor: imageproxy-fi the url
+    imageUrl: APP_FILES_BASE_URL + '/' + activity.image,
+    eventDetails: {
+      description: activity.description,
+      externalLink: activity.location.url,
+      meetingLink: activity.registerUrl,
+    },
+  }
+}
+
+export const fetchEvent = async (input: FetchEventInput) => {
+  const url = new URL(`${APP_API_BASE_URL}/activities/${input.id}`)
+  const startDate = Date.now()
+
+  logger.info(`fetching event from ${url}`)
+
+  const response = await fetch(url)
+
+  if (response.status === 404) {
+    throw new NotFound('Not found')
+  }
+
+  try {
+    const json = (await response.json()).activity as Activity
+
+    const holiEvent = toHoliEvent(json)
+
+    return {
+      data: holiEvent,
+    }
+    // deno-lint-ignore no-explicit-any
+  } catch (e: any) {
+    logger.error(
+      `Error performing request to ${url}: ${e.message}`,
+    )
+    throw e
+  } finally {
+    const duration = Date.now() - startDate
+    logger.debug(`fetching projects took ${duration} ms`)
+  }
+}
diff --git a/app/fetch_event_test.ts b/app/fetch_event_test.ts
new file mode 100644
index 0000000000000000000000000000000000000000..03c8d8f480e1ef6e9a40228c400413c2f2d07096
--- /dev/null
+++ b/app/fetch_event_test.ts
@@ -0,0 +1,60 @@
+import { RealTimedEvent } from './providers/jasd/tests/fixtures.ts'
+import { fetchEvent } from './fetch_event.ts'
+import { returnsNext, stub } from 'https://deno.land/std@0.165.0/testing/mock.ts'
+import { describe, it } from 'https://deno.land/std@0.165.0/testing/bdd.ts'
+import { assertEquals, assertRejects } from 'https://deno.land/std@0.165.0/testing/asserts.ts'
+import NotFound = Deno.errors.NotFound
+
+describe('fetchEvent', () => {
+  it('throws when no event can be fetched', () => {
+    const fakeFetch = stub(
+      globalThis,
+      'fetch',
+      returnsNext([Promise.resolve(new Response(null, { status: 404, statusText: 'Not Found' }))]),
+    )
+
+    assertRejects(() => fetchEvent({ id: 'iDoesNotExist' }), NotFound)
+
+    fakeFetch.restore()
+  })
+
+  it('works for a jasd api response', async () => {
+    const fakeFetch = stub(
+      globalThis,
+      'fetch',
+      returnsNext([Promise.resolve(new Response(JSON.stringify(RealTimedEvent)))]),
+    )
+
+    const expectedEvent = {
+      data: {
+        id: '4610',
+        endDate: '2025-03-26T00:00:00+01:00',
+        eventDetails: {
+          description:
+            '<p>Jeden Dienstag (bis auf eine Sommer- und Winterpause) zeigt der Verein Allerweltskino e.V. im Kölner Filmtheater Off Broadway einen Nachhaltigkeitsfilm. Das Programm ist im Internet abrufbar (siehe Kasten rechts).</p>',
+          externalLink: 'https://www.allerweltskino.de',
+          meetingLink: 'https://www.allerweltskino.de',
+        },
+        imageUrl: 'https://gemeinschaftswerk-nachhaltigkeit.de/app/api/v1/files/activities/act5.jpg',
+        isRemote: false,
+        location: {
+          city: 'Köln',
+          street: 'Bahnhofstr.',
+          streetNo: '41',
+          zipCode: '50674',
+        },
+        organisationName: 'Allerweltskino e.V.',
+        startDate: '2025-03-26T00:00:00+01:00',
+        title: 'RealTimedEvent',
+      },
+    }
+
+    const result = await fetchEvent({ id: '4160' })
+
+    assertEquals(result, expectedEvent)
+
+    fakeFetch.restore()
+  })
+
+  //return 500 errors for internal problems
+})
diff --git a/app/fetch_events.ts b/app/fetch_events.ts
index 11aad7eae27ffd04d3b70ce2d96ee5b37eafe05b..e5439e8808822243f868e81da031929404bdb5c8 100644
--- a/app/fetch_events.ts
+++ b/app/fetch_events.ts
@@ -5,20 +5,20 @@ import { AppApiEvent, AppApiResponse } from './providers/jasd/appapi.dto.types.t
 const APP_API_BASE_URL = 'https://gemeinschaftswerk-nachhaltigkeit.de/app/api/v2'
 const APP_FILES_BASE_URL = 'https://gemeinschaftswerk-nachhaltigkeit.de/app/api/v1/files'
 
-type HoliEventLocation = {
+export type HoliEventLocation = {
   street?: string
   streetNo?: string
   zipCode?: string
   city?: string
 }
 
-type HoliEventDetails = {
+export type HoliEventDetails = {
   description: string
   externalLink: string
   meetingLink?: string
 }
 
-type HoliEvent = {
+export type HoliEvent = {
   id: string
   title: string
   organisationName: string
diff --git a/app/providers/jasd/appapi.dto.types.ts b/app/providers/jasd/appapi.dto.types.ts
index 2ea7a4f20077077f8ea1c1a94cb45e9d177dec8a..c70601aaf27170048911b2dbec0e525bed62e799 100644
--- a/app/providers/jasd/appapi.dto.types.ts
+++ b/app/providers/jasd/appapi.dto.types.ts
@@ -75,7 +75,7 @@ type ActivityType = 'EVENT' | string
 
 type ImpactArea = 'LOCAL' | 'REGIONAL' | 'NATIONAL' | 'INTERNATIONAL' | string
 
-type Activity = {
+export type Activity = {
   id: number
   name: string
   description: string
diff --git a/app/server.ts b/app/server.ts
index 1e390be1076d15b0a60d22e069326beb540d76ba..ca8cc88846b4ba39e1f8b0afc1e953d30c459e14 100644
--- a/app/server.ts
+++ b/app/server.ts
@@ -45,6 +45,10 @@ export type EventsRequest = {
   location?: string
 }
 
+export type EventRequest = {
+  id: string
+}
+
 const validateEventsRequestInput = (request: EventsRequest): FetchEventsInput => {
   console.log(request)
   return {
@@ -54,6 +58,13 @@ const validateEventsRequestInput = (request: EventsRequest): FetchEventsInput =>
   }
 }
 
+const _validateEventRequestInput = (request: EventRequest): FetchEventsInput => {
+  console.log(request)
+  return {
+    id: request.id,
+  }
+}
+
 const createResolvers = (_config: ServerConfig) => ({
   Query: {
     events: (
@@ -72,6 +83,24 @@ const createResolvers = (_config: ServerConfig) => ({
         )
       }
     },
+    /*
+    event: (
+      // deno-lint-ignore no-explicit-any
+      _parent: any,
+      parameters: EventRequest,
+      // next line is required for the resolver to work
+      // deno-lint-ignore no-unused-vars
+      context: GraphQLContext,
+    ): Promise<HoliEventsResponse> => {
+      if (_config.fake) {
+        return Promise.resolve({ totalResults: 0, data: [] })
+      } else {
+        return fetchEvent(
+          validateEventRequestInput(parameters),
+        )
+      }
+    },
+     */
   },
 })
 
diff --git a/deno.lock b/deno.lock
index 6c22ce1a3cf8f695fd31b0e54803c2ab0c358da2..82b4e23c5879f991814044ef4c95de454a89d092 100644
--- a/deno.lock
+++ b/deno.lock
@@ -527,6 +527,13 @@
     "https://deno.land/std@0.156.0/async/pool.ts": "ef9eb97b388543acbf0ac32647121e4dbe629236899586c4d4311a8770fbb239",
     "https://deno.land/std@0.156.0/async/tee.ts": "d27680d911816fcb3d231e16d690e7588079e66a9b2e5ce8cc354db94fdce95f",
     "https://deno.land/std@0.156.0/http/server.ts": "c1bce1cbf4060055f622d5c3f0e406fd553e5dca111ca836d28c6268f170ebeb",
+    "https://deno.land/std@0.165.0/fmt/colors.ts": "9e36a716611dcd2e4865adea9c4bec916b5c60caad4cdcdc630d4974e6bb8bd4",
+    "https://deno.land/std@0.165.0/testing/_diff.ts": "a23e7fc2b4d8daa3e158fa06856bedf5334ce2a2831e8bf9e509717f455adb2c",
+    "https://deno.land/std@0.165.0/testing/_format.ts": "cd11136e1797791045e639e9f0f4640d5b4166148796cad37e6ef75f7d7f3832",
+    "https://deno.land/std@0.165.0/testing/_test_suite.ts": "2d07073d5460a4e3ec50c55ae822cd9bd136926d7363091379947fef9c73c3e4",
+    "https://deno.land/std@0.165.0/testing/asserts.ts": "1e340c589853e82e0807629ba31a43c84ebdcdeca910c4a9705715dfdb0f5ce8",
+    "https://deno.land/std@0.165.0/testing/bdd.ts": "35060cefd9cc21b414f4d89453b3551a3d52ec50aeff25db432503c5485b2f72",
+    "https://deno.land/std@0.165.0/testing/mock.ts": "d7ad40139cda87476c4dc1efeffe406bbfb4a5f82b688e0b85bffe9e911526a2",
     "https://deno.land/std@0.198.0/async/delay.ts": "a6142eb44cdd856b645086af2b811b1fcce08ec06bb7d50969e6a872ee9b8659",
     "https://deno.land/std@0.198.0/collections/_comparators.ts": "fa7f9a44cea1d270098a2a5a6f8bb30c61b595c1b1f983bd67c6297d766adffa",
     "https://deno.land/std@0.198.0/collections/binary_search_node.ts": "8d99dd95901d73a0edbe105826ef7ce0e1111ce184d2d0410dbfda172c9ebf35",