diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index e4924294bb2daafc499aade9225bf197b1c006c6..466b89d0ce227c432730110288373a8c2c50ab4e 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -34,6 +34,7 @@
         "i18next-browser-languagedetector": "^6.1.2",
         "i18next-http-backend": "^1.3.1",
         "libphonenumber-js": "^1.9.35",
+        "lodash": "^4.17.21",
         "react": "^17.0.2",
         "react-datepicker": "^4.2.1",
         "react-dom": "^17.0.2",
@@ -47,6 +48,7 @@
         "web-vitals": "^1.1.2"
       },
       "devDependencies": {
+        "@types/lodash": "^4.14.175",
         "@typescript-eslint/eslint-plugin": "^4.31.1",
         "@typescript-eslint/parser": "^4.31.1",
         "eslint": "^7.32.0",
@@ -57,6 +59,7 @@
         "eslint-plugin-jsx-a11y": "^6.4.1",
         "eslint-plugin-react": "^7.25.1",
         "eslint-plugin-react-hooks": "^4.2.0",
+        "jest-fetch-mock": "^3.0.3",
         "jest-junit": "^12.2.0"
       }
     },
@@ -4788,6 +4791,12 @@
       "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
       "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4="
     },
+    "node_modules/@types/lodash": {
+      "version": "4.14.175",
+      "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.175.tgz",
+      "integrity": "sha512-XmdEOrKQ8a1Y/yxQFOMbC47G/V2VDO1GvMRnl4O75M4GW/abC5tnfzadQYkqEveqRM1dEJGFFegfPNA2vvx2iw==",
+      "dev": true
+    },
     "node_modules/@types/minimatch": {
       "version": "3.0.5",
       "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
@@ -13388,6 +13397,16 @@
         "node": ">=8"
       }
     },
+    "node_modules/jest-fetch-mock": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz",
+      "integrity": "sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==",
+      "dev": true,
+      "dependencies": {
+        "cross-fetch": "^3.0.4",
+        "promise-polyfill": "^8.1.3"
+      }
+    },
     "node_modules/jest-get-type": {
       "version": "26.3.0",
       "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz",
@@ -18929,6 +18948,12 @@
       "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
       "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM="
     },
+    "node_modules/promise-polyfill": {
+      "version": "8.2.1",
+      "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.2.1.tgz",
+      "integrity": "sha512-3p9zj0cEHbp7NVUxEYUWjQlffXqnXaZIMPkAO7HhFh8u5636xLRDHOUo2vpWSK0T2mqm6fKLXYn1KP6PAZ2gKg==",
+      "dev": true
+    },
     "node_modules/prompts": {
       "version": "2.4.0",
       "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.0.tgz",
@@ -28398,6 +28423,12 @@
       "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
       "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4="
     },
+    "@types/lodash": {
+      "version": "4.14.175",
+      "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.175.tgz",
+      "integrity": "sha512-XmdEOrKQ8a1Y/yxQFOMbC47G/V2VDO1GvMRnl4O75M4GW/abC5tnfzadQYkqEveqRM1dEJGFFegfPNA2vvx2iw==",
+      "dev": true
+    },
     "@types/minimatch": {
       "version": "3.0.5",
       "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
@@ -35008,6 +35039,16 @@
         }
       }
     },
+    "jest-fetch-mock": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz",
+      "integrity": "sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==",
+      "dev": true,
+      "requires": {
+        "cross-fetch": "^3.0.4",
+        "promise-polyfill": "^8.1.3"
+      }
+    },
     "jest-get-type": {
       "version": "26.3.0",
       "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz",
@@ -39280,6 +39321,12 @@
       "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
       "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM="
     },
+    "promise-polyfill": {
+      "version": "8.2.1",
+      "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.2.1.tgz",
+      "integrity": "sha512-3p9zj0cEHbp7NVUxEYUWjQlffXqnXaZIMPkAO7HhFh8u5636xLRDHOUo2vpWSK0T2mqm6fKLXYn1KP6PAZ2gKg==",
+      "dev": true
+    },
     "prompts": {
       "version": "2.4.0",
       "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.0.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 1aef0771b8c64246a3e85a30633ee48971f7e995..64f83285b922eebc84efddf35d64cb7452590edb 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -29,6 +29,7 @@
     "i18next-browser-languagedetector": "^6.1.2",
     "i18next-http-backend": "^1.3.1",
     "libphonenumber-js": "^1.9.35",
+    "lodash": "^4.17.21",
     "react": "^17.0.2",
     "react-datepicker": "^4.2.1",
     "react-dom": "^17.0.2",
@@ -74,6 +75,7 @@
     ]
   },
   "devDependencies": {
+    "@types/lodash": "^4.14.175",
     "@typescript-eslint/eslint-plugin": "^4.31.1",
     "@typescript-eslint/parser": "^4.31.1",
     "eslint": "^7.32.0",
diff --git a/frontend/public/locales/en/common.json b/frontend/public/locales/en/common.json
index 72dc93f99c41110ed0bff661a0a2f503dc954921..06e4febf51b28aca1862859d25620c884fe789fd 100644
--- a/frontend/public/locales/en/common.json
+++ b/frontend/public/locales/en/common.json
@@ -34,6 +34,12 @@
     "endNow": "End role",
     "overviewGuest": "Guest overview"
   },
+  "register": {
+    "registerHeading": "Register new guest",
+    "registerText": "Please search for e-mail or phone number before registering a new guest to prevent duplicates.",
+    "registerButtonText": "Register new guest"
+  },
+
   "loading": "Loading...",
   "termsHeader": "Terms",
   "staging": "Staging",
diff --git a/frontend/public/locales/nb/common.json b/frontend/public/locales/nb/common.json
index 4a8c036881fb149cf71cd602d25c1fa14cb81c58..0a715f9e268d974c3d151c401c6233c4550d87aa 100644
--- a/frontend/public/locales/nb/common.json
+++ b/frontend/public/locales/nb/common.json
@@ -34,6 +34,11 @@
     "endNow": "Avslutt rolle",
     "overviewGuest": "Oversikt over gjest"
   },
+  "register": {
+    "registerHeading": "Registrer ny gjest",
+    "registerText": "Søk etter e-post eller mobilnummer før du registrerer ny gjest for å unngå dobbeltoppføringer.",
+    "registerButtonText": "Registrer ny gjest"
+  },
   "loading": "Laster...",
   "termsHeader": "Vilkår",
   "staging": "Staging",
diff --git a/frontend/public/locales/nn/common.json b/frontend/public/locales/nn/common.json
index f58c9dd1c25ee44e92497fdf7ab74cbb4ce6e923..7cfe9c12f4ece559cdff4a4fc9e35824ef0bb2aa 100644
--- a/frontend/public/locales/nn/common.json
+++ b/frontend/public/locales/nn/common.json
@@ -35,6 +35,11 @@
     "endNow": "Avslutt rolle",
     "overviewGuest": "Oversikt over gjest"
   },
+  "register": {
+    "registerHeading": "Registrer ny gjest",
+    "registerText": "Søk etter e-post eller mobilnummer før du registrerer ny gjest for å unngå dobbeltoppføringer.",
+    "registerButtonText": "Registrer ny gjest"
+  },
   "loading": "Lastar...",
   "termsHeader": "Vilkår",
   "staging": "Staging",
diff --git a/frontend/src/interfaces/index.ts b/frontend/src/interfaces/index.ts
index 8bf895596e6ecffc99e3336e4ffc7f4fd932e876..9dad342987b651d1e214c55b6aa0159d8dccf4fd 100644
--- a/frontend/src/interfaces/index.ts
+++ b/frontend/src/interfaces/index.ts
@@ -1,34 +1,43 @@
 export type Guest = {
-  id: string
   pid: string
-  name: string
+  first: string
+  last: string
   email: string
   mobile: string
   fnr: string
-  role_nb: string
-  role_en: string
-  max_days: number
-  start_date: Date
-  end_date: Date
   active: boolean
-  ou_nb: string
-  ou_en: string
+  roles: Role[]
 }
 
 export interface FetchedGuest {
-  id: string
   pid: string
   first: string
   last: string
   email: string
   mobile: string
   fnr: string
-  role_nb: string
-  role_en: string
+  active: boolean
+  roles: FetchedRole[]
+}
+
+export type Role = {
+  id: string
+  name_nb: string
+  name_en: string
+  ou_nb: string
+  ou_en: string
+  start_date: Date
+  end_date: Date
   max_days: number
-  start_date: string
-  end_date: string
+}
+
+export type FetchedRole = {
+  id: string
+  name_nb: string
+  name_en: string
   ou_nb: string
   ou_en: string
-  active: boolean
+  start_date: string
+  end_date: string
+  max_days: number
 }
diff --git a/frontend/src/routes/sponsor/frontpage/index.tsx b/frontend/src/routes/sponsor/frontpage/index.tsx
index c7d8ef85218e6105071f55f28c82eb2109a6b379..3d2a10a52df14bc04392158ee467121478680c82 100644
--- a/frontend/src/routes/sponsor/frontpage/index.tsx
+++ b/frontend/src/routes/sponsor/frontpage/index.tsx
@@ -17,7 +17,7 @@ import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
 import Page from 'components/page'
 import { useTranslation } from 'react-i18next'
 import { Link } from 'react-router-dom'
-import { Guest } from 'interfaces'
+import { Guest, Role } from 'interfaces'
 import format from 'date-fns/format'
 import SponsorGuestButtons from '../../components/sponsorGuestButtons'
 
@@ -26,28 +26,29 @@ interface GuestProps {
 }
 interface PersonLineProps {
   person: Guest
+  role: Role
 }
 
-const PersonLine = ({ person }: PersonLineProps) => {
+const PersonLine = ({ person, role }: PersonLineProps) => {
   const [t, i18n] = useTranslation(['common'])
 
   return (
     <TableRow
-      key={person.name}
+      key={`${person.first} ${person.last}`}
       sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
     >
       <TableCell component="th" scope="row">
-        {person.name}
+        {`${person.first} ${person.last}`}
       </TableCell>
       <TableCell align="left">
-        {i18n.language === 'en' ? person.role_en : person.role_nb}
+        {i18n.language === 'en' ? role.name_en : role.name_nb}
       </TableCell>
       <TableCell align="left">
-        {person.start_date ? format(person.start_date, 'yyyy-MM-dd') : null} -{' '}
-        {format(person.end_date, 'yyyy-MM-dd')}
+        {role.start_date ? format(role.start_date, 'yyyy-MM-dd') : null} -{' '}
+        {format(role.end_date, 'yyyy-MM-dd')}
       </TableCell>
       <TableCell align="left">
-        {i18n.language === 'en' ? person.ou_en : person.ou_nb}
+        {i18n.language === 'en' ? role.ou_en : role.ou_nb}
       </TableCell>
       <TableCell align="left">
         <Button
@@ -95,9 +96,19 @@ const ActiveGuests = ({ persons }: GuestProps) => {
               </TableRow>
             </TableHead>
             <TableBody>
-              {guests.map((person) => (
-                <PersonLine person={person} />
-              ))}
+              {guests.length > 0 ? (
+                guests.map((person) =>
+                  person.roles ? (
+                    person.roles.map((role) => (
+                      <PersonLine role={role} person={person} />
+                    ))
+                  ) : (
+                    <></>
+                  )
+                )
+              ) : (
+                <></>
+              )}
 
               <TableRow>
                 <TableCell>
@@ -148,9 +159,19 @@ const WaitingGuests = ({ persons }: GuestProps) => {
               </TableRow>
             </TableHead>
             <TableBody>
-              {guests.map((person) => (
-                <PersonLine person={person} />
-              ))}
+              {guests.length > 0 ? (
+                guests.map((person) =>
+                  person.roles ? (
+                    person.roles.map((role) => (
+                      <PersonLine role={role} person={person} />
+                    ))
+                  ) : (
+                    <></>
+                  )
+                )
+              ) : (
+                <></>
+              )}
               <TableRow>
                 <TableCell>
                   {guests.length > 0 ? '' : t('common:noWaitingGuests')}
diff --git a/frontend/src/routes/sponsor/guestInfo/index.tsx b/frontend/src/routes/sponsor/guestInfo/index.tsx
index d65301202da844d5a8946c785d96342383fa1b60..0e46c0799d6437f6554eec76fe5732d1bae6513c 100644
--- a/frontend/src/routes/sponsor/guestInfo/index.tsx
+++ b/frontend/src/routes/sponsor/guestInfo/index.tsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import React, { useEffect, useState } from 'react'
 import { Link, useParams } from 'react-router-dom'
 
 import Page from 'components/page'
@@ -13,39 +13,41 @@ import {
   TableRow,
   Paper,
 } from '@mui/material'
-import { Guest } from 'interfaces'
+import { Guest, Role, FetchedRole } from 'interfaces'
 import SponsorInfoButtons from 'routes/components/sponsorInfoButtons'
-import format from 'date-fns/format'
+import { format } from 'date-fns'
+import { parseRole } from 'utils'
 
 type GuestInfoParams = {
   pid: string
 }
 interface RoleLineProps {
-  guest: Guest
+  role: Role
+  pid: string
 }
 
-const RoleLine = ({ guest }: RoleLineProps) => {
+const RoleLine = ({ role, pid }: RoleLineProps) => {
   const [t, i18n] = useTranslation('common')
   return (
     <TableRow
-      key={guest.id}
+      key={role.id}
       sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
     >
       <TableCell align="left">
-        {i18n.language === 'en' ? guest.role_en : guest.role_nb}
+        {i18n.language === 'en' ? role.name_en : role.name_nb}
       </TableCell>
       <TableCell component="th" scope="row">
-        {guest.start_date ? format(guest.start_date, 'yyyy-MM-dd') : null} -{' '}
-        {format(guest.end_date, 'yyyy-MM-dd')}
+        {role.start_date ? format(role.start_date, 'yyyy-MM-dd') : null} -{' '}
+        {format(role.end_date, 'yyyy-MM-dd')}
       </TableCell>
       <TableCell align="left">
-        {i18n.language === 'en' ? guest.ou_en : guest.ou_nb}
+        {i18n.language === 'en' ? role.ou_en : role.ou_nb}
       </TableCell>
       <TableCell>
         <Button
           variant="contained"
           component={Link}
-          to={`/sponsor/guest/${guest.pid}/roles/${guest.id}`}
+          to={`/sponsor/guest/${pid}/roles/${role.id}`}
         >
           {t('sponsor.choose')}
         </Button>
@@ -54,16 +56,46 @@ const RoleLine = ({ guest }: RoleLineProps) => {
   )
 }
 
-interface GuestInfoProps {
-  guests: Guest[]
-}
-
-export default function GuestInfo({ guests }: GuestInfoProps) {
+export default function GuestInfo() {
   const { pid } = useParams<GuestInfoParams>()
   const [t] = useTranslation(['common'])
+  const [guestInfo, setGuest] = useState<Guest>({
+    pid: '',
+    first: '',
+    last: '',
+    email: '',
+    fnr: '',
+    mobile: '',
+    active: false,
+    roles: [],
+  })
+  const [roles, setRoles] = useState<Role[]>([])
+
+  const getPerson = async (id: string) => {
+    try {
+      const response = await fetch(`/api/ui/v1/person/${id}`)
+      const rjson = await response.json()
+      if (response.ok) {
+        setGuest({
+          pid: rjson.pid,
+          first: rjson.first,
+          last: rjson.last,
+          email: rjson.email,
+          mobile: rjson.mobile,
+          fnr: rjson.fnr,
+          active: rjson.active,
+          roles: rjson.roles,
+        })
+        setRoles(rjson.roles.map((role: FetchedRole) => parseRole(role)))
+      }
+    } catch (error) {
+      console.error(error)
+    }
+  }
 
-  const roles = guests.filter((guest) => guest.pid.toString() === pid)
-  const guestInfo = roles[0]
+  useEffect(() => {
+    getPerson(pid)
+  }, [])
 
   return (
     <Page>
@@ -80,7 +112,9 @@ export default function GuestInfo({ guests }: GuestInfoProps) {
           <TableBody>
             <TableRow>
               <TableCell align="left">{t('input.fullName')}</TableCell>
-              <TableCell align="left">{guestInfo.name}</TableCell>
+              <TableCell align="left">
+                {`${guestInfo.first} ${guestInfo.last}`}
+              </TableCell>
             </TableRow>
             <TableRow>
               <TableCell align="left">{t('input.email')}</TableCell>
@@ -109,8 +143,8 @@ export default function GuestInfo({ guests }: GuestInfoProps) {
             </TableRow>
           </TableHead>
           <TableBody>
-            {roles.map((guest) => (
-              <RoleLine guest={guest} />
+            {roles.map((role) => (
+              <RoleLine pid={pid} role={role} />
             ))}
           </TableBody>
         </Table>
diff --git a/frontend/src/routes/sponsor/guestRoleInfo/index.tsx b/frontend/src/routes/sponsor/guestRoleInfo/index.tsx
index c135f7f7dfb70bf0a57c1aaa816e7e744d03de13..fed60946e6e9cb66f1af5518f2e2f2d1582609d4 100644
--- a/frontend/src/routes/sponsor/guestRoleInfo/index.tsx
+++ b/frontend/src/routes/sponsor/guestRoleInfo/index.tsx
@@ -61,15 +61,18 @@ export default function GuestRoleInfo({ guests }: GuestRoleInfoProps) {
   const [t, i18n] = useTranslation('common')
 
   // Find the role info relevant for this page
-  const role = guests.filter((guest) => guest.id.toString() === id)[0]
+  const guestInfo = guests.filter((guest) => guest.pid.toString() === pid)[0]
+  const roleInfo = guestInfo.roles.filter(
+    (role) => role.id.toString() === id
+  )[0]
 
   // Prepare min and max date values
   const today = new Date()
-  const todayPlusMaxDays = addDays(role.max_days)(today)
+  const todayPlusMaxDays = addDays(roleInfo.max_days)(today)
 
   // Make a function for use with onClick of the end role button
   const endPeriod = () => () => {
-    role.end_date = today
+    roleInfo.end_date = today
     endPeriodPost(id, { end_date: today })
   }
 
@@ -123,7 +126,7 @@ export default function GuestRoleInfo({ guests }: GuestRoleInfoProps) {
               <TableRow>
                 <TableCell align="left">{t('common:role')}</TableCell>
                 <TableCell>
-                  {i18n.language === 'en' ? role.role_en : role.role_nb}
+                  {i18n.language === 'en' ? roleInfo.name_en : roleInfo.name_nb}
                 </TableCell>
               </TableRow>
               <TableRow>
@@ -132,11 +135,13 @@ export default function GuestRoleInfo({ guests }: GuestRoleInfoProps) {
                   <Controller
                     name="start_date"
                     control={control}
-                    defaultValue={role.start_date}
+                    defaultValue={roleInfo.start_date}
                     render={({ field: { onChange, value } }) => (
                       <DatePicker
                         mask="____-__-__"
-                        disabled={role.start_date.getDate() <= today.getDate()}
+                        disabled={
+                          roleInfo.start_date.getDate() <= today.getDate()
+                        }
                         label={t('input.roleStartDate')}
                         value={value}
                         minDate={today}
@@ -152,12 +157,12 @@ export default function GuestRoleInfo({ guests }: GuestRoleInfoProps) {
                   <Controller
                     name="end_date"
                     control={control}
-                    defaultValue={role.end_date}
+                    defaultValue={roleInfo.end_date}
                     render={({ field: { onChange, value } }) => (
                       <DatePicker
                         mask="____-__-__"
                         label={t('input.roleEndDate')}
-                        disabled={role.end_date.getDate() < today.getDate()}
+                        disabled={roleInfo.end_date.getDate() < today.getDate()}
                         minDate={today}
                         maxDate={todayPlusMaxDays}
                         value={value}
@@ -175,7 +180,7 @@ export default function GuestRoleInfo({ guests }: GuestRoleInfoProps) {
               <TableRow>
                 <TableCell align="left">{t('common:ou')}</TableCell>
                 <TableCell align="left">
-                  {i18n.language === 'en' ? role.ou_en : role.ou_nb}
+                  {i18n.language === 'en' ? roleInfo.ou_en : roleInfo.ou_nb}
                 </TableCell>
                 <TableCell align="left" />
               </TableRow>
diff --git a/frontend/src/routes/sponsor/index.tsx b/frontend/src/routes/sponsor/index.tsx
index 7e44ab00f1e1b9fd1bf4c2bb19e3a2261d107989..e097b1b0881e35efcb447c5c4da83dd9e66ddde6 100644
--- a/frontend/src/routes/sponsor/index.tsx
+++ b/frontend/src/routes/sponsor/index.tsx
@@ -5,6 +5,7 @@ import FrontPage from 'routes/sponsor/frontpage'
 import GuestInfo from 'routes/sponsor/guestInfo'
 import GuestRoleInfo from 'routes/sponsor/guestRoleInfo'
 import { FetchedGuest, Guest } from 'interfaces'
+import { parseRole } from 'utils'
 
 function Sponsor() {
   const [guests, setGuests] = useState<Guest[]>([])
@@ -14,27 +15,21 @@ function Sponsor() {
       const response = await fetch('/api/ui/v1/guests/?format=json')
       const jsonResponse = await response.json()
       if (response.ok) {
-        const roles = await jsonResponse.roles
+        const persons = await jsonResponse.persons
         setGuests(
-          roles.map((person: FetchedGuest) => ({
-            id: person.id,
-            pid: person.pid,
-            name: `${person.first} ${person.last}`,
-            email: person.email,
-            mobile: person.mobile,
-            fnr: person.fnr,
-            role_nb: person.role_nb,
-            role_en: person.role_en,
-            max_days: person.max_days,
-            start_date: new Date(Date.parse(person.start_date)),
-            end_date: new Date(Date.parse(person.end_date)),
-            active: person.active,
-            ou_nb: person.ou_nb,
-            ou_en: person.ou_en,
-          }))
+          persons.map(
+            (person: FetchedGuest): Guest => ({
+              pid: person.pid,
+              first: person.first,
+              last: person.last,
+              email: person.email,
+              mobile: person.mobile,
+              fnr: person.fnr,
+              active: person.active,
+              roles: person.roles.map((role) => parseRole(role)),
+            })
+          )
         )
-      } else {
-        setGuests([])
       }
     } catch (error) {
       setGuests([])
@@ -51,7 +46,7 @@ function Sponsor() {
         <GuestRoleInfo guests={guests} />
       </Route>
       <Route exact path="/sponsor/guest/:pid">
-        <GuestInfo guests={guests} />
+        <GuestInfo />
       </Route>
       <Route exact path="/sponsor">
         <FrontPage guests={guests} />
diff --git a/frontend/src/routes/sponsor/register/frontPage.tsx b/frontend/src/routes/sponsor/register/frontPage.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..297e6abbba6db139f8d9bb05dd59d08f1840a37f
--- /dev/null
+++ b/frontend/src/routes/sponsor/register/frontPage.tsx
@@ -0,0 +1,71 @@
+import { Button, InputAdornment, MenuItem, TextField } from '@mui/material'
+import Page from 'components/page'
+import { Link } from 'react-router-dom'
+import SponsorGuestButtons from 'routes/components/sponsorGuestButtons'
+import SearchIcon from '@mui/icons-material/Search'
+import { useTranslation } from 'react-i18next'
+import { debounce } from 'lodash'
+import React, { useState } from 'react'
+
+type Guest = {
+  first: string
+  last: string
+  pid: string
+  value: string
+}
+
+function FrontPage() {
+  const [t] = useTranslation('common')
+  const [guests, setGuests] = useState<Guest[]>([])
+
+  const getGuests = async (event: React.ChangeEvent<HTMLInputElement>) => {
+    if (event.target.value) {
+      console.log('searching')
+      const response = await fetch(
+        `/api/ui/v1/person/search/${event.target.value}`
+      )
+      const repjson = await response.json()
+      console.log(repjson)
+      if (response.ok) {
+        setGuests(repjson.persons)
+      }
+    }
+  }
+  return (
+    <Page>
+      <SponsorGuestButtons registerNewGuestActive />
+      <h4>{t('register.registerHeading')}</h4>
+      <p>{t('register.registerText')}</p>
+      <TextField
+        InputProps={{
+          endAdornment: (
+            <InputAdornment position="end">
+              <SearchIcon />
+            </InputAdornment>
+          ),
+        }}
+        fullWidth
+        placeholder="Mobile phone, e-mail"
+        onChange={debounce(getGuests, 600)}
+      />
+      {guests ? (
+        guests.map((guest) => {
+          const guestTo = `/sponsor/guest/${guest.pid}`
+          return (
+            <MenuItem component={Link} to={guestTo}>
+              {guest.first} {guest.last}
+              <br />
+              {guest.value}
+            </MenuItem>
+          )
+        })
+      ) : (
+        <></>
+      )}
+      <Button variant="contained" component={Link} to="register/new">
+        {t('register.registerButtonText')}
+      </Button>
+    </Page>
+  )
+}
+export default FrontPage
diff --git a/frontend/src/routes/sponsor/register/index.test.tsx b/frontend/src/routes/sponsor/register/index.test.tsx
index 9dbbc897e7a17086950531c91034710fcfe54a7e..4d699b4f5553db156fb04195321f346c8ec6231a 100644
--- a/frontend/src/routes/sponsor/register/index.test.tsx
+++ b/frontend/src/routes/sponsor/register/index.test.tsx
@@ -3,12 +3,12 @@ import { render, waitFor, screen } from 'test-utils'
 import userEvent from '@testing-library/user-event'
 import AdapterDateFns from '@mui/lab/AdapterDateFns'
 import { LocalizationProvider } from '@mui/lab'
-import Register from './index'
+import StepRegistration from './stepRegistration'
 
 test('Validation message showing if last name is missing', async () => {
   render(
     <LocalizationProvider dateAdapter={AdapterDateFns}>
-      <Register />
+      <StepRegistration />
     </LocalizationProvider>
   )
 
diff --git a/frontend/src/routes/sponsor/register/index.tsx b/frontend/src/routes/sponsor/register/index.tsx
index a93b29c9d16d52c50aa965f9de4edbcd4a8769a3..c53b35efb1d991310e97b429c6b490ebf6d50e32 100644
--- a/frontend/src/routes/sponsor/register/index.tsx
+++ b/frontend/src/routes/sponsor/register/index.tsx
@@ -1,191 +1,17 @@
-import React, { useState, useRef } from 'react'
-import { useTranslation } from 'react-i18next'
-
-import { Box, Button } from '@mui/material'
-import Page from 'components/page'
-
-import { useHistory } from 'react-router-dom'
-import format from 'date-fns/format'
-import { RegisterFormData } from './formData'
-import StepSummary from './stepSummary'
-import StepPersonForm from './stepPersonForm'
-import { PersonFormMethods } from './personFormMethods'
-import SubmitState from './submitState'
-import SponsorGuestButtons from '../../components/sponsorGuestButtons'
-import { submitJsonOpts } from '../../../utils'
-import StepSubmitSuccess from './stepSubmitSuccess'
-
-enum Steps {
-  RegisterStep = 0,
-  SummaryStep = 1,
-  SuccessStep = 2,
-}
-
-/**
- *
- * This component controls the invite process where the sponsor
- * enters the initial information about a guest.
- *
- */
-export default function StepRegistration() {
-  const { t } = useTranslation(['common'])
-  const [formData, setFormData] = useState<RegisterFormData>({
-    first_name: undefined,
-    last_name: undefined,
-    role_type: undefined,
-    role_start: undefined,
-    role_end: undefined,
-    comment: undefined,
-    ou_id: undefined,
-    email: undefined,
-  })
-  const history = useHistory()
-
-  const [activeStep, setActiveStep] = useState(0)
-  const personFormRef = useRef<PersonFormMethods>(null)
-  const [submitState, setSubmitState] = useState(SubmitState.NotSubmitted)
-
-  const handleNext = () => {
-    if (activeStep === 0) {
-      if (personFormRef.current) {
-        personFormRef.current.doSubmit()
-      }
-    } else {
-      setActiveStep((prevActiveStep) => prevActiveStep + 1)
-    }
-  }
-
-  const registerGuest = () => {
-    const payload = {
-      first_name: formData.first_name,
-      last_name: formData.last_name,
-      email: formData.email,
-      role: {
-        type: formData.role_type,
-        start_date:
-          formData.role_start === null
-            ? null
-            : format(formData.role_start as Date, 'yyyy-MM-dd'),
-        end_date:
-          formData.role_end === null
-            ? null
-            : format(formData.role_end as Date, 'yyyy-MM-dd'),
-        comments: formData.comment,
-        orgunit_id: formData.ou_id,
-      },
-    }
-
-    console.log('submitting', JSON.stringify(payload))
-    fetch('/api/ui/v1/invite/', submitJsonOpts('POST', payload))
-      .then((res) => {
-        if (!res.ok) {
-          setSubmitState(SubmitState.SubmitFailure)
-          return null
-        }
-        return res.text()
-      })
-      .then((result) => {
-        if (result !== null) {
-          console.log('result', result)
-          setSubmitState(SubmitState.SubmitSuccess)
-          setActiveStep(Steps.SuccessStep)
-        }
-      })
-      .catch((error) => {
-        console.log('error', error)
-        setSubmitState(SubmitState.SubmitFailure)
-      })
-  }
-
-  const handleBack = () => {
-    setActiveStep((prevActiveStep) => prevActiveStep - 1)
-  }
-
-  const handleForwardFromRegister = (
-    updateFormData: RegisterFormData
-  ): void => {
-    setFormData(updateFormData)
-    setActiveStep((prevActiveStep) => prevActiveStep + 1)
-  }
-
-  const handleCancel = () => {
-    history.push('/')
-  }
+import { Route } from 'react-router-dom'
+import FrontPage from './frontPage'
+import StepRegistration from './stepRegistration'
 
+function Register() {
   return (
-    <Page>
-      <SponsorGuestButtons registerNewGuestActive />
-      {/* Current page in wizard */}
-      <Box sx={{ width: '100%' }}>
-        {activeStep === Steps.RegisterStep && (
-          <StepPersonForm
-            nextHandler={handleForwardFromRegister}
-            formData={formData}
-            ref={personFormRef}
-          />
-        )}
-        {activeStep === Steps.SummaryStep && (
-          <StepSummary formData={formData} />
-        )}
-      </Box>
-
-      <Box
-        sx={{
-          display: 'flex',
-          flexDirection: 'row',
-          pt: 2,
-          color: 'primary.main',
-          paddingBottom: '1rem',
-        }}
-      >
-        {activeStep === Steps.RegisterStep && (
-          <Button
-            data-testid="button-next"
-            sx={{ color: 'theme.palette.secondary', mr: 1 }}
-            onClick={handleNext}
-          >
-            {t('button.next')}
-          </Button>
-        )}
-
-        {activeStep === Steps.SummaryStep && (
-          <>
-            <Button
-              onClick={handleBack}
-              disabled={submitState === SubmitState.SubmitSuccess}
-              sx={{ mr: 1 }}
-            >
-              {t('button.back')}
-            </Button>
-
-            <Button
-              onClick={registerGuest}
-              disabled={submitState === SubmitState.SubmitSuccess}
-              sx={{ mr: 1 }}
-            >
-              {t('button.save')}
-            </Button>
-          </>
-        )}
-
-        {activeStep !== Steps.SuccessStep && (
-          <Button
-            onClick={handleCancel}
-            disabled={submitState === SubmitState.SubmitSuccess}
-          >
-            {t('button.cancel')}
-          </Button>
-        )}
-      </Box>
-
-      {activeStep === Steps.SuccessStep && <StepSubmitSuccess />}
-
-      {/* TODO For now just showing a heading to give the user some feedback */}
-      {submitState === SubmitState.SubmitFailure && (
-        <Box>
-          <h2>Submit failure</h2>
-        </Box>
-      )}
-    </Page>
+    <>
+      <Route path="/register/new">
+        <StepRegistration />
+      </Route>
+      <Route exact path="/register">
+        <FrontPage />
+      </Route>
+    </>
   )
 }
+export default Register
diff --git a/frontend/src/routes/sponsor/register/stepRegistration.tsx b/frontend/src/routes/sponsor/register/stepRegistration.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..a93b29c9d16d52c50aa965f9de4edbcd4a8769a3
--- /dev/null
+++ b/frontend/src/routes/sponsor/register/stepRegistration.tsx
@@ -0,0 +1,191 @@
+import React, { useState, useRef } from 'react'
+import { useTranslation } from 'react-i18next'
+
+import { Box, Button } from '@mui/material'
+import Page from 'components/page'
+
+import { useHistory } from 'react-router-dom'
+import format from 'date-fns/format'
+import { RegisterFormData } from './formData'
+import StepSummary from './stepSummary'
+import StepPersonForm from './stepPersonForm'
+import { PersonFormMethods } from './personFormMethods'
+import SubmitState from './submitState'
+import SponsorGuestButtons from '../../components/sponsorGuestButtons'
+import { submitJsonOpts } from '../../../utils'
+import StepSubmitSuccess from './stepSubmitSuccess'
+
+enum Steps {
+  RegisterStep = 0,
+  SummaryStep = 1,
+  SuccessStep = 2,
+}
+
+/**
+ *
+ * This component controls the invite process where the sponsor
+ * enters the initial information about a guest.
+ *
+ */
+export default function StepRegistration() {
+  const { t } = useTranslation(['common'])
+  const [formData, setFormData] = useState<RegisterFormData>({
+    first_name: undefined,
+    last_name: undefined,
+    role_type: undefined,
+    role_start: undefined,
+    role_end: undefined,
+    comment: undefined,
+    ou_id: undefined,
+    email: undefined,
+  })
+  const history = useHistory()
+
+  const [activeStep, setActiveStep] = useState(0)
+  const personFormRef = useRef<PersonFormMethods>(null)
+  const [submitState, setSubmitState] = useState(SubmitState.NotSubmitted)
+
+  const handleNext = () => {
+    if (activeStep === 0) {
+      if (personFormRef.current) {
+        personFormRef.current.doSubmit()
+      }
+    } else {
+      setActiveStep((prevActiveStep) => prevActiveStep + 1)
+    }
+  }
+
+  const registerGuest = () => {
+    const payload = {
+      first_name: formData.first_name,
+      last_name: formData.last_name,
+      email: formData.email,
+      role: {
+        type: formData.role_type,
+        start_date:
+          formData.role_start === null
+            ? null
+            : format(formData.role_start as Date, 'yyyy-MM-dd'),
+        end_date:
+          formData.role_end === null
+            ? null
+            : format(formData.role_end as Date, 'yyyy-MM-dd'),
+        comments: formData.comment,
+        orgunit_id: formData.ou_id,
+      },
+    }
+
+    console.log('submitting', JSON.stringify(payload))
+    fetch('/api/ui/v1/invite/', submitJsonOpts('POST', payload))
+      .then((res) => {
+        if (!res.ok) {
+          setSubmitState(SubmitState.SubmitFailure)
+          return null
+        }
+        return res.text()
+      })
+      .then((result) => {
+        if (result !== null) {
+          console.log('result', result)
+          setSubmitState(SubmitState.SubmitSuccess)
+          setActiveStep(Steps.SuccessStep)
+        }
+      })
+      .catch((error) => {
+        console.log('error', error)
+        setSubmitState(SubmitState.SubmitFailure)
+      })
+  }
+
+  const handleBack = () => {
+    setActiveStep((prevActiveStep) => prevActiveStep - 1)
+  }
+
+  const handleForwardFromRegister = (
+    updateFormData: RegisterFormData
+  ): void => {
+    setFormData(updateFormData)
+    setActiveStep((prevActiveStep) => prevActiveStep + 1)
+  }
+
+  const handleCancel = () => {
+    history.push('/')
+  }
+
+  return (
+    <Page>
+      <SponsorGuestButtons registerNewGuestActive />
+      {/* Current page in wizard */}
+      <Box sx={{ width: '100%' }}>
+        {activeStep === Steps.RegisterStep && (
+          <StepPersonForm
+            nextHandler={handleForwardFromRegister}
+            formData={formData}
+            ref={personFormRef}
+          />
+        )}
+        {activeStep === Steps.SummaryStep && (
+          <StepSummary formData={formData} />
+        )}
+      </Box>
+
+      <Box
+        sx={{
+          display: 'flex',
+          flexDirection: 'row',
+          pt: 2,
+          color: 'primary.main',
+          paddingBottom: '1rem',
+        }}
+      >
+        {activeStep === Steps.RegisterStep && (
+          <Button
+            data-testid="button-next"
+            sx={{ color: 'theme.palette.secondary', mr: 1 }}
+            onClick={handleNext}
+          >
+            {t('button.next')}
+          </Button>
+        )}
+
+        {activeStep === Steps.SummaryStep && (
+          <>
+            <Button
+              onClick={handleBack}
+              disabled={submitState === SubmitState.SubmitSuccess}
+              sx={{ mr: 1 }}
+            >
+              {t('button.back')}
+            </Button>
+
+            <Button
+              onClick={registerGuest}
+              disabled={submitState === SubmitState.SubmitSuccess}
+              sx={{ mr: 1 }}
+            >
+              {t('button.save')}
+            </Button>
+          </>
+        )}
+
+        {activeStep !== Steps.SuccessStep && (
+          <Button
+            onClick={handleCancel}
+            disabled={submitState === SubmitState.SubmitSuccess}
+          >
+            {t('button.cancel')}
+          </Button>
+        )}
+      </Box>
+
+      {activeStep === Steps.SuccessStep && <StepSubmitSuccess />}
+
+      {/* TODO For now just showing a heading to give the user some feedback */}
+      {submitState === SubmitState.SubmitFailure && (
+        <Box>
+          <h2>Submit failure</h2>
+        </Box>
+      )}
+    </Page>
+  )
+}
diff --git a/frontend/src/utils/index.ts b/frontend/src/utils/index.ts
index fcb7c0da28e37afd12aa65ae24e6ef183cccc783..116236660180cbf20095854333cba435dd940f72 100644
--- a/frontend/src/utils/index.ts
+++ b/frontend/src/utils/index.ts
@@ -1,5 +1,7 @@
 import validator from '@navikt/fnrvalidator'
+import { parseISO } from 'date-fns'
 import i18n from 'i18next'
+import { FetchedRole, Role } from 'interfaces'
 import { isValidPhoneNumber, parsePhoneNumber } from 'libphonenumber-js'
 
 const validEmailRegex =
@@ -97,3 +99,16 @@ export function splitPhoneNumber(phoneNumber: string): [string, string] {
     parsedNumber.nationalNumber.toString(),
   ]
 }
+
+export function parseRole(role: FetchedRole): Role {
+  return {
+    id: role.id,
+    name_nb: role.name_nb,
+    name_en: role.name_en,
+    ou_nb: role.ou_nb,
+    ou_en: role.ou_en,
+    start_date: parseISO(role.start_date),
+    end_date: parseISO(role.end_date),
+    max_days: role.max_days,
+  }
+}
diff --git a/gregui/api/urls.py b/gregui/api/urls.py
index e5b04c50770d4f49878d8cae700d0d4fd677d102..db1d56dbedfee7dafec148cde4f959575ef5d864 100644
--- a/gregui/api/urls.py
+++ b/gregui/api/urls.py
@@ -7,6 +7,7 @@ from gregui.api.views.invitation import (
     CreateInvitationView,
     InvitedGuestView,
 )
+from gregui.api.views.person import PersonSearchView, PersonView
 from gregui.api.views.roletypes import RoleTypeViewSet
 from gregui.api.views.unit import UnitsViewSet
 
@@ -19,4 +20,8 @@ urlpatterns += [
     path("invited/", InvitedGuestView.as_view(), name="invited-info"),
     path("invited/<uuid>", CheckInvitationView.as_view(), name="invite-verify"),
     path("invite/", CreateInvitationView.as_view(), name="invite-create"),
+    path("person/<int:id>", PersonView.as_view(), name="person-get"),
+    path(
+        "person/search/<searchstring>", PersonSearchView.as_view(), name="person-search"
+    ),
 ]
diff --git a/gregui/api/views/person.py b/gregui/api/views/person.py
new file mode 100644
index 0000000000000000000000000000000000000000..edf0239f1ba71026ae331db29b29a04b5e6c9e10
--- /dev/null
+++ b/gregui/api/views/person.py
@@ -0,0 +1,75 @@
+from django.http.response import JsonResponse
+from rest_framework.authentication import SessionAuthentication, BasicAuthentication
+from rest_framework.permissions import IsAuthenticated
+from rest_framework.views import APIView
+
+from greg.models import Identity, Person
+from greg.permissions import IsSponsor
+
+
+class PersonView(APIView):
+    """
+    Fetch person info for any guest as long as you are a sponsor
+
+    This is required for the functionality where a sponsor wants to add a guest role to
+    an already existing person that is not already their guest.
+
+    Returns enough information to fill a profile page in the frontend
+    """
+
+    authentication_classes = [SessionAuthentication, BasicAuthentication]
+    permission_classes = [IsAuthenticated, IsSponsor]
+
+    def get(self, request, id):
+        person = Person.objects.get(id=id)
+        response = {
+            "pid": person.id,
+            "first": person.first_name,
+            "last": person.last_name,
+            "email": person.private_email and person.private_email.value,
+            "mobile": person.private_mobile and person.private_mobile.value,
+            "fnr": person.fnr and "".join((person.fnr.value[:-5], "*****")),
+            "roles": [
+                {
+                    "id": role.id,
+                    "name_nb": role.type.name_nb,
+                    "name_en": role.type.name_en,
+                    "ou_nb": role.orgunit_id.name_nb,
+                    "ou_en": role.orgunit_id.name_en,
+                    "start_date": role.start_date,
+                    "end_date": role.end_date,
+                    "max_days": role.type.max_days,
+                }
+                for role in person.roles.all()
+            ],
+        }
+        return JsonResponse(response)
+
+
+class PersonSearchView(APIView):
+    """Search for persons using email or phone number"""
+
+    authentication_classes = [SessionAuthentication, BasicAuthentication]
+    permission_classes = [IsAuthenticated, IsSponsor]
+
+    def get(self, requests, searchstring):
+        search = Identity.objects.filter(
+            value__icontains=searchstring,  # icontains to include wrong case emails
+            type__in=[
+                Identity.IdentityType.PRIVATE_EMAIL,
+                Identity.IdentityType.PRIVATE_MOBILE_NUMBER,
+            ],
+        )[:10]
+        response = {
+            "persons": [
+                {
+                    "pid": i.person.id,
+                    "first": i.person.first_name,
+                    "last": i.person.last_name,
+                    "value": i.value,
+                    "type": i.type,
+                }
+                for i in search
+            ]
+        }
+        return JsonResponse(response)
diff --git a/gregui/views.py b/gregui/views.py
index 19ef21e57f59d1fbe835ad04b3b6197ab35d9f3a..b2be0d591e74caddb26178d6b9985d17c41afea9 100644
--- a/gregui/views.py
+++ b/gregui/views.py
@@ -6,7 +6,7 @@ from rest_framework.authentication import SessionAuthentication, BasicAuthentica
 from rest_framework.permissions import IsAuthenticated
 from rest_framework.views import APIView
 
-from greg.models import Role, Sponsor
+from greg.models import Person, Sponsor
 from greg.permissions import IsSponsor
 from gregui import mailutils
 from gregui.models import GregUserProfile
@@ -85,6 +85,8 @@ class OusView(APIView):
 
 
 class GuestInfoView(APIView):
+    """Fetch all the sponsors guests"""
+
     authentication_classes = [SessionAuthentication, BasicAuthentication]
     permission_classes = [IsAuthenticated, IsSponsor]
 
@@ -92,30 +94,35 @@ class GuestInfoView(APIView):
     # pylint: disable=W0622
     def get(request, format=None):
         user = GregUserProfile.objects.get(user=request.user)
+
         return JsonResponse(
             {
-                "roles": [
+                "persons": [
                     {
-                        "id": i.id,
-                        "pid": i.person.id,
-                        "first": i.person.first_name,
-                        "last": i.person.last_name,
-                        "email": i.person.private_email
-                        and i.person.private_email.value,
-                        "mobile": i.person.private_mobile
-                        and i.person.private_mobile.value,
-                        "fnr": i.person.fnr
-                        and "".join((i.person.fnr.value[:-5], "*****")),
-                        "role_nb": i.type.name_nb,
-                        "role_en": i.type.name_en,
-                        "max_days": i.type.max_days,
-                        "start_date": i.start_date and i.start_date.isoformat(),
-                        "end_date": i.end_date.isoformat(),
-                        "ou_nb": i.orgunit_id.name_nb,
-                        "ou_en": i.orgunit_id.name_en,
-                        "active": i.person.is_registered and i.person.is_verified,
+                        "pid": person.id,
+                        "first": person.first_name,
+                        "last": person.last_name,
+                        "email": person.private_email and person.private_email.value,
+                        "mobile": person.private_mobile and person.private_mobile.value,
+                        "fnr": person.fnr and "".join((person.fnr.value[:-5], "*****")),
+                        "active": person.is_registered and person.is_verified,
+                        "roles": [
+                            {
+                                "id": role.id,
+                                "name_nb": role.type.name_nb,
+                                "name_en": role.type.name_en,
+                                "ou_nb": role.orgunit_id.name_nb,
+                                "ou_en": role.orgunit_id.name_en,
+                                "start_date": role.start_date,
+                                "end_date": role.end_date,
+                                "max_days": role.type.max_days,
+                            }
+                            for role in person.roles.all()
+                        ],
                     }
-                    for i in Role.objects.filter(sponsor_id=user.sponsor)
+                    for person in Person.objects.filter(
+                        roles__sponsor_id=user.sponsor
+                    ).distinct()
                 ]
             }
         )