diff --git a/.vscode/settings.json b/.vscode/settings.json
index c5cf6632f8d8c9dd3a503ba10ec94c4f01efe993..d2f1afdc05168415c392035b4aef1bc1351e3e85 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -48,7 +48,9 @@
     "ecolyo",
     "enedis",
     "Enedis",
+    "firstname",
     "grdf",
+    "lastname",
     "luxon",
     "toastify",
     "wysiwyg",
diff --git a/src/components/Consents/GrdfConsents.tsx b/src/components/Consents/GrdfConsents.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..af2f868500f09068859074feaae5ab44899e31e8
--- /dev/null
+++ b/src/components/Consents/GrdfConsents.tsx
@@ -0,0 +1,317 @@
+import { Button, TablePagination, TextField } from '@mui/material'
+import {
+  ColDef,
+  ColGroupDef,
+  CsvExportParams,
+  GridApi,
+  GridReadyEvent,
+  IRowNode,
+  RowSelectedEvent,
+  ValueFormatterParams,
+} from 'ag-grid-community'
+import { AgGridReact } from 'ag-grid-react'
+import { DateTime } from 'luxon'
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import { useWhoAmI } from '../../API'
+import { getAxiosXSRFHeader } from '../../axios.config'
+import { IGrdfConsent } from '../../models/grdfConsent'
+import { GrdfConsentService } from '../../services/grdfConsent.service'
+import DownloadModal from './DownloadModal'
+import './agGridOverrides.scss'
+import styles from './consents.module.scss'
+
+export const GrdfConsents: React.FC = () => {
+  const [gridApi, setGridApi] = useState<GridApi | null>(null)
+  const [search, setSearch] = useState<string>('')
+  const [selectedNodes, setSelectedNodes] = useState<IRowNode[]>([])
+  const [isShowingSelection, setIsShowingSelection] = useState<boolean>(false)
+  const [openDownloadModal, setOpenDownloadModal] = useState<boolean>(false)
+  const [consents, setConsents] = useState<IGrdfConsent[]>([])
+  const [page, setPage] = useState<number>(0)
+  const [rowsPerPage, setRowsPerPage] = useState<number>(50)
+  const [totalRows, setTotalRows] = useState<number>(50)
+  const { data: user } = useWhoAmI()
+  const consentService = useMemo(() => {
+    return new GrdfConsentService()
+  }, [])
+
+  const toggleOpenModal = useCallback(() => {
+    setOpenDownloadModal(prev => !prev)
+  }, [])
+
+  const defaultColDef = useMemo(
+    () => ({
+      sortable: true,
+      resizable: true,
+    }),
+    []
+  )
+
+  const dateFormatter = (data: ValueFormatterParams): string => {
+    return (data.value as DateTime).toLocaleString()
+  }
+
+  const [columnDefs] = useState<(ColDef | ColGroupDef)[] | null>([
+    {
+      field: 'ID',
+      hide: true,
+    },
+    {
+      field: 'pce',
+      headerName: 'N° PCE',
+      initialWidth: 180,
+      filter: true,
+      checkboxSelection: true,
+    },
+    {
+      field: 'lastname',
+      headerName: 'Nom',
+      initialWidth: 180,
+      filter: true,
+      cellStyle: { textTransform: 'uppercase' },
+    },
+    {
+      field: 'firstname',
+      headerName: 'Prénom',
+      initialWidth: 180,
+      filter: true,
+      cellStyle: { textTransform: 'capitalize' },
+    },
+    {
+      field: 'postalCode',
+      headerName: 'CP',
+      initialWidth: 80,
+      filter: true,
+    },
+    {
+      field: 'startDate',
+      valueFormatter: dateFormatter,
+      headerName: 'Début du consentement',
+      initialWidth: 150,
+      filter: true,
+      sort: 'desc',
+    },
+    {
+      field: 'endDate',
+      valueFormatter: dateFormatter,
+      headerName: 'Fin du consentement',
+      initialWidth: 150,
+      filter: true,
+    },
+  ])
+
+  const handleChangePage = useCallback(
+    (
+      _event: React.MouseEvent<HTMLButtonElement, MouseEvent> | null,
+      newPage: number
+    ) => {
+      setPage(newPage)
+    },
+    []
+  )
+  const handleChangeRowsPerPage = useCallback(event => {
+    setRowsPerPage(event.target.value)
+    setPage(0)
+  }, [])
+
+  const checkSelectedNodes = useCallback(() => {
+    if (gridApi) {
+      const newNodes = gridApi.getRenderedNodes()
+      const idsToCheck: string[] = selectedNodes
+        .filter(node => node.isSelected)
+        .map(node => node.data.ID)
+
+      newNodes.forEach(node => {
+        if (idsToCheck.includes(node.data.ID)) node.setSelected(true, false)
+      })
+    }
+  }, [gridApi, selectedNodes])
+
+  const searchConsents = async () => {
+    if (user) {
+      const consentPagination = await consentService.searchConsents(
+        search,
+        rowsPerPage,
+        page,
+        getAxiosXSRFHeader(user.xsrftoken)
+      )
+      if (consentPagination) {
+        setConsents(consentPagination.rows)
+        checkSelectedNodes()
+        setTotalRows(consentPagination.totalRows)
+      }
+    }
+  }
+
+  const handleSearchChange = (newSearch: string) => {
+    setSearch(newSearch)
+    setPage(0)
+  }
+
+  const resetSelection = useCallback(() => {
+    if (gridApi) {
+      setIsShowingSelection(false)
+      gridApi.setRowData(consents)
+      gridApi.deselectAll()
+      setSelectedNodes([])
+    }
+  }, [gridApi, consents])
+
+  const onRowSelected = useCallback(
+    (event: RowSelectedEvent) => {
+      if (event.node.isSelected()) {
+        const index = selectedNodes.findIndex(
+          node => node.data.ID === event.node.data.ID
+        )
+        if (index === -1) {
+          setSelectedNodes(prev => [...prev, event.node])
+        }
+      } else {
+        setSelectedNodes(prev =>
+          prev.filter(node => {
+            return node.data.ID != event.node.data.ID
+          })
+        )
+      }
+    },
+    [selectedNodes]
+  )
+
+  const continueSelection = useCallback(() => {
+    if (gridApi) {
+      setIsShowingSelection(false)
+      gridApi?.setRowData(consents)
+      const newNodes = gridApi.getRenderedNodes()
+      // We have to select nodes that have already been selected since we cannot pass a Node array to init AgGrid
+      const idsToCheck: string[] = selectedNodes
+        .filter(node => node.isSelected)
+        .map(node => node.data.ID)
+
+      newNodes.forEach(node => {
+        if (idsToCheck.includes(node.data.ID)) node.setSelected(true)
+      })
+    }
+  }, [gridApi, consents, selectedNodes])
+
+  const showCurrentSelection = useCallback(() => {
+    setIsShowingSelection(true)
+    const dataFromNode = selectedNodes.map(item => item.data)
+    selectedNodes && gridApi?.setRowData(dataFromNode)
+    gridApi?.selectAll()
+  }, [gridApi, selectedNodes])
+
+  const exportData = useCallback(() => {
+    //You can change default column separator
+    const params: CsvExportParams = {
+      columnSeparator: ',',
+    }
+    gridApi?.exportDataAsCsv(params)
+    setOpenDownloadModal(false)
+    resetSelection()
+  }, [gridApi, resetSelection])
+
+  const onGridReady = ({ api }: GridReadyEvent) => {
+    //Grid init method
+    setGridApi(api)
+    api.sizeColumnsToFit()
+  }
+
+  useEffect(() => {
+    function handleResize() {
+      gridApi?.sizeColumnsToFit()
+    }
+    handleResize()
+    window.addEventListener('resize', handleResize)
+    return () => {
+      window.removeEventListener('resize', handleResize)
+    }
+  }, [gridApi])
+
+  /** Trigger search when page loads or when admin changes input or pagination */
+  useEffect(() => {
+    searchConsents()
+    // /!\ Do not change dependencies or effect will not trigger when pagination changes
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [rowsPerPage, page, search])
+
+  return (
+    <>
+      <div className="header">
+        <h1>Consentements GRDF</h1>
+      </div>
+      <div className={styles.content}>
+        <TextField
+          placeholder="N°PCE (14 chiffres)"
+          label="Recherche"
+          value={search}
+          onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
+            handleSearchChange(e.target.value)
+          }
+          disabled={isShowingSelection}
+          autoComplete="off"
+        />
+        <div
+          className="ag-theme-alpine-dark"
+          style={{ width: '100%', height: '75vh' }}
+        >
+          <AgGridReact
+            onGridReady={onGridReady}
+            defaultColDef={defaultColDef}
+            rowHeight={35}
+            rowData={consents}
+            columnDefs={columnDefs}
+            animateRows={true}
+            rowSelection="multiple"
+            allowDragFromColumnsToolPanel={false}
+            onRowSelected={onRowSelected}
+            sortingOrder={['asc', 'desc']}
+            rowMultiSelectWithClick={true}
+            pagination={false}
+            suppressCellFocus={true}
+            rowClassRules={{
+              expired: params => params.data.endDate < DateTime.now(),
+            }}
+          />
+          {!isShowingSelection && (
+            <TablePagination
+              labelRowsPerPage="Consentements par page"
+              component="div"
+              count={totalRows}
+              page={page}
+              onPageChange={handleChangePage}
+              rowsPerPage={rowsPerPage}
+              onRowsPerPageChange={handleChangeRowsPerPage}
+              rowsPerPageOptions={[10, 25, 50, 100]}
+            />
+          )}
+        </div>
+        <DownloadModal
+          open={openDownloadModal}
+          toggleOpenModal={toggleOpenModal}
+          exportData={exportData}
+        />
+      </div>
+      <div className={styles.footerButtons}>
+        <Button
+          variant="outlined"
+          onClick={isShowingSelection ? continueSelection : resetSelection}
+          disabled={
+            !isShowingSelection && selectedNodes && selectedNodes.length === 0
+          }
+        >
+          {isShowingSelection
+            ? 'Continuer ma sélection'
+            : 'Tout désélectionner'}
+        </Button>
+        <Button
+          onClick={!isShowingSelection ? showCurrentSelection : toggleOpenModal}
+          disabled={selectedNodes && selectedNodes.length <= 0}
+          classes={{ contained: styles.btnText }}
+        >
+          {!isShowingSelection ? 'Voir mes sélections' : 'Télécharger'}
+          <div>{selectedNodes?.length}</div>
+        </Button>
+      </div>
+    </>
+  )
+}
diff --git a/src/components/Consents/Consents.tsx b/src/components/Consents/SgeConsents.tsx
similarity index 98%
rename from src/components/Consents/Consents.tsx
rename to src/components/Consents/SgeConsents.tsx
index 3ee1795cd2e64bf942fb02059a99936283619954..f31a476746e6e4c7b75bdba99a2052086d7d2bc6 100644
--- a/src/components/Consents/Consents.tsx
+++ b/src/components/Consents/SgeConsents.tsx
@@ -19,9 +19,8 @@ import { SgeConsentService } from '../../services/sgeConsent.service'
 import DownloadModal from './DownloadModal'
 import './agGridOverrides.scss'
 import styles from './consents.module.scss'
-import './muiPaginationOverrides.scss'
 
-const Consents: React.FC = () => {
+export const SgeConsents: React.FC = () => {
   const [gridApi, setGridApi] = useState<GridApi | null>(null)
   const [search, setSearch] = useState<string>('')
   const [selectedNodes, setSelectedNodes] = useState<IRowNode[]>([])
@@ -254,7 +253,7 @@ const Consents: React.FC = () => {
   return (
     <>
       <div className="header">
-        <h1>Gestion des consentements Enedis</h1>
+        <h1>Consentements Enedis</h1>
       </div>
       <div className={styles.content}>
         <TextField
@@ -332,4 +331,3 @@ const Consents: React.FC = () => {
     </>
   )
 }
-export default Consents
diff --git a/src/components/Consents/muiPaginationOverrides.scss b/src/components/Consents/muiPaginationOverrides.scss
deleted file mode 100644
index a759bd019b0e87beabe0086d6507b8ff39ca87c5..0000000000000000000000000000000000000000
--- a/src/components/Consents/muiPaginationOverrides.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-// Overrides MaterialUI Paginiation styles
-
-.MuiMenuItem-root {
-  color: black !important;
-}
diff --git a/src/components/Routes/Router.tsx b/src/components/Routes/Router.tsx
index 386cf72d8c9b990353d12ce696c3a5877b6c4bdd..9b651a64d09b326796a7df3861a320e6d62efbf6 100644
--- a/src/components/Routes/Router.tsx
+++ b/src/components/Routes/Router.tsx
@@ -1,6 +1,7 @@
 import { Navigate, Route, Routes } from 'react-router-dom'
 import { useWhoAmI } from '../../API'
-import Consents from '../Consents/Consents'
+import { GrdfConsents } from '../Consents/GrdfConsents'
+import { SgeConsents } from '../Consents/SgeConsents'
 import Loader from '../Loader/Loader'
 import Login from '../Login/Login'
 import Newsletter from '../Newsletter/Newsletter'
@@ -57,7 +58,16 @@ const Router = () => {
             <Route path={links.prices.path} element={<Prices />} />
             <Route path="/popups" element={<Popups />} />
             {user.isAdmin && (
-              <Route path={links.sgeConsents.path} element={<Consents />} />
+              <>
+                <Route
+                  path={links.sgeConsents.path}
+                  element={<SgeConsents />}
+                />
+                <Route
+                  path={links.grdfConsents.path}
+                  element={<GrdfConsents />}
+                />
+              </>
             )}
             <Route path="/login" element={<Login />} />
             <Route
diff --git a/src/models/grdfConsent.ts b/src/models/grdfConsent.ts
index 20490a5944af648682f40adf45779b75544956b4..7f7e3c5f54952c713b566a14ecb2816034a3670b 100644
--- a/src/models/grdfConsent.ts
+++ b/src/models/grdfConsent.ts
@@ -1,7 +1,6 @@
 import { DateTime } from 'luxon'
-
 export interface IGrdfConsent
-  extends Omit<GrdfConsentEntity, 'CreatedAt' | 'endDate' | 'inseeCode'> {
+  extends Omit<GrdfConsentEntity, 'CreatedAt' | 'endDate'> {
   startDate: DateTime
   endDate: DateTime
 }
@@ -12,12 +11,8 @@ export interface GrdfConsentEntity {
   endDate: string
   firstname: string
   lastname: string
-  pointID: number
-  address: string
+  pce: number
   postalCode: string
-  inseeCode: string
-  city: string
-  safetyOnBoarding: boolean
 }
 
 export interface IGrdfConsentPagination
diff --git a/src/models/sgeConsent.model.ts b/src/models/sgeConsent.model.ts
index fe09f1300080502b82424dd703dfef5283534ef0..224ba0e913409ea408c6669b234990d552960378 100644
--- a/src/models/sgeConsent.model.ts
+++ b/src/models/sgeConsent.model.ts
@@ -1,4 +1,5 @@
 import { DateTime } from 'luxon'
+
 export interface ISgeConsent
   extends Omit<SgeConsentEntity, 'CreatedAt' | 'endDate' | 'inseeCode'> {
   startDate: DateTime
diff --git a/src/services/grdfConsent.service.ts b/src/services/grdfConsent.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6fe987d2871c6a13450fdcb8b3311ea6dcea294c
--- /dev/null
+++ b/src/services/grdfConsent.service.ts
@@ -0,0 +1,83 @@
+import axios, { AxiosRequestConfig } from 'axios'
+import { DateTime } from 'luxon'
+import { toast } from 'react-toastify'
+import {
+  GrdfConsentEntity,
+  GrdfConsentPaginationEntity,
+  IGrdfConsent,
+  IGrdfConsentPagination,
+} from '../models/grdfConsent'
+
+export class GrdfConsentService {
+  /**
+   * Search for consents
+   * @param search
+   * @param limit
+   * @param page
+   * @param axiosHeaders
+   */
+  public searchConsents = async (
+    search: string,
+    limit: number,
+    page: number,
+    axiosHeaders: AxiosRequestConfig
+  ): Promise<IGrdfConsentPagination | null> => {
+    try {
+      const { data } = await axios.get<GrdfConsentPaginationEntity>(
+        `/api/admin/grdf/consent?search=${search}&limit=${limit}&page=${page}`,
+        axiosHeaders
+      )
+      return this.parseConsentPagination(data)
+    } catch (e) {
+      if (e.response.status === 403) {
+        toast.error("Accès refusé : vous n'avez pas les droits nécessaires")
+      } else {
+        toast.error('Erreur lors de la récupération des consentements')
+      }
+      console.error(e)
+      return null
+    }
+  }
+
+  /**
+   * Converts consent entity into consent
+   * @param consentEntity
+   */
+  public parseConsent = (consentEntity: GrdfConsentEntity): IGrdfConsent => {
+    const startDate = DateTime.fromISO(consentEntity.CreatedAt, {
+      zone: 'utc',
+    }).setLocale('fr-FR')
+    const endDate = DateTime.fromISO(consentEntity.endDate, {
+      zone: 'utc',
+    }).setLocale('fr-FR')
+
+    return {
+      ID: consentEntity.ID,
+      startDate: startDate,
+      endDate: endDate,
+      firstname: consentEntity.firstname,
+      lastname: consentEntity.lastname,
+      pce: consentEntity.pce,
+      postalCode: consentEntity.postalCode,
+    }
+  }
+
+  /**
+   * Converts consent pagination entity into consent pagination
+   * @param consentPaginationEntity
+   */
+  public parseConsentPagination = (
+    consentPaginationEntity: GrdfConsentPaginationEntity
+  ): IGrdfConsentPagination => {
+    const rows = consentPaginationEntity.rows.map(consent =>
+      this.parseConsent(consent)
+    )
+
+    const consentPagination: IGrdfConsentPagination = {
+      rows: rows,
+      totalRows: consentPaginationEntity.totalRows,
+      totalPages: consentPaginationEntity.totalPages,
+    }
+    return consentPagination
+  }
+}