diff --git a/app/common_test.ts b/app/common_test.ts
index 0ed39373a29cc031e701c89ea0747fa34639102d..a876f7ac85ad57d6675b5f77dbc971140842ade4 100644
--- a/app/common_test.ts
+++ b/app/common_test.ts
@@ -3,14 +3,20 @@ import { GraphQLServer } from "./server.ts";
 
 export type ResponsePayload = Record<string, unknown> | Array<unknown> | Error;
 
-export const stubFetch = (response: ResponsePayload) => {
+export const stubFetchWithResponses = (responses: ResponsePayload[]) => {
   return stub(
     globalThis,
     "fetch",
-    returnsNext([Promise.resolve(new Response(JSON.stringify(response)))]),
+    returnsNext(
+      responses.map((response) => Promise.resolve(new Response(JSON.stringify(response)))),
+    ),
   );
 };
 
+export const stubFetch = (response: ResponsePayload) => {
+  return stubFetchWithResponses([response]);
+};
+
 export const processGqlRequest = (
   graphQLServer: GraphQLServer,
   query: string,
diff --git a/app/dev_deps.ts b/app/dev_deps.ts
index 59b65bea4e37c96d763fb21465fe0dc579d214e6..57be6074547d4791c63a4137fa2fb9c13a19599e 100644
--- a/app/dev_deps.ts
+++ b/app/dev_deps.ts
@@ -1,11 +1,12 @@
 export {
   assertSpyCall,
   assertSpyCalls,
+  restore,
   returnsNext,
   type Spy,
   spy,
+  type Stub,
   stub,
 } from "https://deno.land/std@0.155.0/testing/mock.ts";
-export type { Stub } from "https://deno.land/std@0.155.0/testing/mock.ts";
 export { assertEquals, assertExists, assertRejects } from "https://deno.land/std@0.155.0/testing/asserts.ts";
-export { afterEach, describe, it } from "https://deno.land/std@0.155.0/testing/bdd.ts";
+export { beforeEach, describe, it } from "https://deno.land/std@0.155.0/testing/bdd.ts";
diff --git a/app/geo_api_client.ts b/app/geo_api_client.ts
index 6a14360331bbe471a0ccc2efced020d1e36a1a92..b847481a322e423777f943b64e361ed0bf5edc1d 100644
--- a/app/geo_api_client.ts
+++ b/app/geo_api_client.ts
@@ -1,16 +1,27 @@
-import { GeolocationCoordinates, GeolocationGeometry } from "./types.ts";
+import { GeolocationCoordinates, GeolocationGeometry, GeolocationProperties } from "./types.ts";
+import { logger } from "./logging.ts";
 
 type GeoAPIResponse = {
   data?: {
     placeDetails?: {
       geolocation?: {
-        properties?: Partial<GeolocationCoordinates>;
+        properties?: Partial<GeolocationProperties>;
         geometry?: Partial<GeolocationGeometry>;
       };
     };
   };
 };
 
+type GeoAPIPlace = {
+  id?: string;
+};
+
+type GeoAPIAutocompleteResponse = {
+  data?: {
+    placesAutocomplete?: GeoAPIPlace[];
+  };
+};
+
 export class GeoAPIClient {
   private readonly geoAPIEndpointUrl: string;
 
@@ -33,6 +44,21 @@ export class GeoAPIClient {
     return response.json() as GeoAPIResponse;
   }
 
+  private async resolvePlaceIdByName(name: string): Promise<string | undefined> {
+    const graphQLQuery = `{ placesAutocomplete(text: "${name}", limit: 1) { id } }`;
+    const response = await fetch(this.geoAPIEndpointUrl, {
+      "body": JSON.stringify({ query: graphQLQuery }),
+      "headers": {
+        "Accept": "application/graphql-response+json, application/json",
+        "Content-Type": "application/json",
+      },
+      "method": "POST",
+    });
+    const { data } = await response.json() as GeoAPIAutocompleteResponse;
+    const [place] = data?.placesAutocomplete || [];
+    return place?.id;
+  }
+
   async resolveCoordinates(
     geolocationId: string,
   ): Promise<GeolocationCoordinates> {
@@ -50,11 +76,22 @@ export class GeoAPIClient {
 
   async resolveGeometry(
     geolocationId: string,
+    {
+      allowPoints = false,
+    }: { allowPoints?: boolean } = {},
   ): Promise<GeolocationGeometry> {
     const responseJSON = await this.resolveGeolocationViaGeoAPI(geolocationId);
-    const { type, coordinates } = responseJSON.data?.placeDetails?.geolocation
-      ?.geometry || {};
+    const { geometry, properties } = responseJSON.data?.placeDetails?.geolocation || {};
+    const { type, coordinates } = geometry || {};
     if (type && coordinates) {
+      const locationName = properties?.formatted;
+      if (type === "Point" && !allowPoints && locationName) {
+        logger.debug(`Retrieved point as geolocation, will retry with lookup for location ${locationName}`);
+        const placeId = await this.resolvePlaceIdByName(locationName);
+        if (placeId && placeId !== geolocationId) {
+          return this.resolveGeometry(placeId, { allowPoints: true });
+        }
+      }
       return { type, coordinates };
     } else {
       return Promise.reject(
diff --git a/app/geo_api_client_test.ts b/app/geo_api_client_test.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8bb8c5412b64ceaf79274ab13726d0125d8c22e6
--- /dev/null
+++ b/app/geo_api_client_test.ts
@@ -0,0 +1,134 @@
+import { stubFetch, stubFetchWithResponses } from "./common_test.ts";
+import { assertRejects, restore } from "./dev_deps.ts";
+import { assertEquals, beforeEach, describe, it } from "./dev_deps.ts";
+import { GeoAPIClient } from "./geo_api_client.ts";
+
+const testEndpointUrl = "https://endpoint.geo";
+const testPlaceId = "place123";
+const geometryMultipolygon = {
+  "type": "MultiPolygon",
+  "coordinates": [
+    [
+      [
+        [8.1044993, 54.025049999],
+        [8.2109892, 53.980715499],
+      ],
+    ],
+  ],
+};
+const geometryPoint = {
+  type: "Point",
+  coordinates: [10.000654, 53.550340999],
+};
+const geolocationProperties = {
+  formatted: "Hamburg, Germany",
+};
+const geometryResponseMultipolygon = {
+  data: {
+    placeDetails: {
+      geolocation: {
+        properties: geolocationProperties,
+        geometry: geometryMultipolygon,
+      },
+    },
+  },
+};
+const geometryResponsePoint = {
+  data: {
+    placeDetails: {
+      geolocation: {
+        properties: geolocationProperties,
+        geometry: geometryPoint,
+      },
+    },
+  },
+};
+const autocompleteResponse = {
+  data: {
+    placesAutocomplete: [{
+      id: "place1234",
+    }],
+  },
+};
+const invalidResponse = {};
+
+describe("GeoAPIClient", () => {
+  let client: GeoAPIClient;
+
+  beforeEach(() => {
+    restore();
+    client = new GeoAPIClient(testEndpointUrl);
+  });
+
+  describe("resolveGeometry", () => {
+    it("fetches geometry for place id", async () => {
+      stubFetch(geometryResponseMultipolygon);
+
+      const response = await client.resolveGeometry(testPlaceId);
+
+      assertEquals(response, geometryMultipolygon);
+    });
+
+    it("throws error for invalid response when fetching geometry", async () => {
+      stubFetch(invalidResponse);
+
+      await assertRejects(() => client.resolveGeometry(testPlaceId));
+    });
+
+    it("retries fetching geometry if geometry is only a point", async () => {
+      stubFetchWithResponses([geometryResponsePoint, autocompleteResponse, geometryResponseMultipolygon]);
+
+      const response = await client.resolveGeometry(testPlaceId);
+
+      assertEquals(response, geometryMultipolygon);
+    });
+
+    it("does not retry fetching geometry if points are allowed", async () => {
+      stubFetchWithResponses([geometryResponsePoint]);
+
+      const response = await client.resolveGeometry(testPlaceId, { allowPoints: true });
+
+      assertEquals(response, geometryPoint);
+    });
+
+    it("only retries fetching geometry if geometry is only a point once", async () => {
+      stubFetchWithResponses([geometryResponsePoint, autocompleteResponse, geometryResponsePoint]);
+
+      const response = await client.resolveGeometry(testPlaceId);
+
+      assertEquals(response, geometryPoint);
+    });
+
+    it("only retries fetching geometry if autocomplete request results in a different place", async () => {
+      const autocompleteResponseSamePlaceId = [{ id: testPlaceId }];
+      stubFetchWithResponses([geometryResponsePoint, autocompleteResponseSamePlaceId]);
+
+      const response = await client.resolveGeometry(testPlaceId);
+
+      assertEquals(response, geometryPoint);
+    });
+
+    it("handles empty autocomplete response when retrying fetching geometry", async () => {
+      const emptyAutocompleteResponse = { data: { placesAutocomplete: [] } };
+      stubFetchWithResponses([geometryResponsePoint, emptyAutocompleteResponse]);
+
+      const response = await client.resolveGeometry(testPlaceId);
+
+      assertEquals(response, geometryPoint);
+    });
+
+    it("handles invalid autocomplete response when retrying fetching geometry", async () => {
+      stubFetchWithResponses([geometryResponsePoint, invalidResponse]);
+
+      const response = await client.resolveGeometry(testPlaceId);
+
+      assertEquals(response, geometryPoint);
+    });
+
+    it("throws error for invalid geometry response when retrying fetching geometry", async () => {
+      stubFetchWithResponses([geometryResponsePoint, autocompleteResponse, invalidResponse]);
+
+      await assertRejects(() => client.resolveGeometry(testPlaceId));
+    });
+  });
+});
diff --git a/app/types.ts b/app/types.ts
index 75530ad5b1219217cfe275fd51b79d36ed7a58d5..f81988af12ad5c2f9dbf39c899f654d89834e006 100644
--- a/app/types.ts
+++ b/app/types.ts
@@ -80,8 +80,12 @@ export type GeolocationCoordinates = {
   lon: number;
 };
 
+export type GeolocationProperties = {
+  formatted: string;
+} & GeolocationCoordinates;
+
 export type GeolocationGeoJSON = {
-  properties: GeolocationCoordinates;
+  properties: GeolocationProperties;
   geometry: GeolocationGeometry;
 };
 
diff --git a/app/voltastics_test.ts b/app/voltastics_test.ts
index 9e53d22d02024833e27fc63e2c3e5452ba8256b5..4805306b1439b79a24f2dc727e68674d3260d277 100644
--- a/app/voltastics_test.ts
+++ b/app/voltastics_test.ts
@@ -1,8 +1,8 @@
 import {
-  afterEach,
   assertEquals,
   assertRejects,
   assertSpyCall,
+  beforeEach,
   describe,
   it,
   returnsNext,
@@ -94,7 +94,7 @@ const queryEngagement = async (
 const queryCategories = async (
   graphQLServer: GraphQLServer,
 ): Promise<CategoriesResponse> => {
-  const promise = processGqlRequest(
+  const response = await processGqlRequest(
     graphQLServer,
     `
       query categories {
@@ -107,7 +107,7 @@ const queryCategories = async (
     {},
   );
 
-  return (await promise)?.categories as CategoriesResponse;
+  return response?.categories as CategoriesResponse;
 };
 
 const voltasticsConfigMock: VoltasticsConfig = {
@@ -156,7 +156,7 @@ const noCacheServerConfig = {
 describe("voltastics", () => {
   let fetchStub: Stub;
 
-  afterEach(() => {
+  beforeEach(() => {
     fetchStub?.restore();
   });