diff --git a/docker-compose.local.yml b/docker-compose.local.yml
index b9807f3ce022bb9177c8e11bdbe91f1fc5e31820..33bb965cb0c094b23da67bfb4a07990fec476259 100644
--- a/docker-compose.local.yml
+++ b/docker-compose.local.yml
@@ -79,7 +79,7 @@ services:
       - ${OAUTH_PORT}:${OAUTH_PORT}
   keycloak:
     container_name: camino_keycloak
-    image: quay.io/keycloak/keycloak:26.1.0
+    image: caminofr/camino-keycloak:26.1.0
     depends_on:
       - db
     environment:
@@ -88,11 +88,6 @@ services:
       KC_DB_SCHEMA: keycloak
       KC_DB_PASSWORD: "${PGPASSWORD}"
       KC_DB_USERNAME: "${PGUSER}"
-    volumes:
-      - $PWD/infra/roles/camino/files/keycloak-franceconnect-7.0.0.jar:/opt/keycloak/providers/keycloak-franceconnect-7.0.0.jar
-      - $PWD/infra/roles/camino/files/keycloak-theme-for-kc-26-and-above.jar:/opt/keycloak/providers/keycloak-theme-for-kc-26-and-above.jar
-      - $PWD/infra/roles/camino/files/keycloak-bcrypt-1.6.0.jar:/opt/keycloak/providers/keycloak-bcrypt-1.6.0.jar
-      - $PWD/infra/roles/camino/files/keycloak_theme/:/opt/keycloak/themes/camino/
     command:
       - '/opt/keycloak/bin/kc.sh build && /opt/keycloak/bin/kc.sh start-dev --hostname=127.0.0.1 --spi-theme-static-max-age=-1 --spi-theme-cache-themes=false --spi-theme-cache-templates=false'
     entrypoint: "/bin/bash -c"
diff --git a/packages/api/src/api/rest/format/titres.ts b/packages/api/src/api/rest/format/titres.ts
index 0ef4e23feac05eeb98eb59eca0d8cb40f964c408..09311408d32898e9b258d186937e793a841b269f 100644
--- a/packages/api/src/api/rest/format/titres.ts
+++ b/packages/api/src/api/rest/format/titres.ts
@@ -30,12 +30,11 @@ const getFacadesMaritimeCell = (secteursMaritime: SecteursMaritimes[], separator
     .join(separator)
 
 const titreContenuTableFormat = (titre: ITitre): Record<string, string> => {
-  if (isNullOrUndefinedOrEmpty(titre.demarches)) {
+  const orderedDemarches = titre.demarches?.filter(d => !DemarchesTypes[d.typeId].travaux).toSorted((a, b) => (b.ordre ?? 0) - (a.ordre ?? 0))
+
+  if (isNullOrUndefinedOrEmpty(orderedDemarches)) {
     return {}
   }
-
-  const orderedDemarches = titre.demarches.filter(d => !DemarchesTypes[d.typeId].travaux).toSorted((a, b) => (b.ordre ?? 0) - (a.ordre ?? 0))
-
   const demarche = orderedDemarches[0]
   const etapes = (demarche.etapes ?? []).map(etape => {
     const sections = getSections(titre.typeId, demarche.typeId, etape.typeId)
diff --git a/packages/api/src/api/rest/index.test.integration.ts b/packages/api/src/api/rest/index.test.integration.ts
new file mode 100644
index 0000000000000000000000000000000000000000..659be2afafc31f04db948896231d5aa5999dae6b
--- /dev/null
+++ b/packages/api/src/api/rest/index.test.integration.ts
@@ -0,0 +1,103 @@
+import { dbManager } from '../../../tests/db-manager'
+import { afterAll, beforeAll, test, expect, vi, describe } from 'vitest'
+import type { Pool } from 'pg'
+import { newTitreId } from '../../database/models/_format/id-create'
+import { insertTitreGraph } from '../../../tests/integration-test-helper'
+import { titreSlugValidator } from 'camino-common/src/validators/titres'
+import { restDownloadCall } from '../../../tests/_utils'
+import { ADMINISTRATION_IDS } from 'camino-common/src/static/administrations'
+import { HTTP_STATUS } from 'camino-common/src/http'
+
+console.info = vi.fn()
+console.error = vi.fn()
+
+let dbPool: Pool
+
+beforeAll(async () => {
+  const { pool } = await dbManager.populateDb()
+  dbPool = pool
+
+  const titreId = newTitreId('titre-id-1-for-import')
+  const titreSlug = titreSlugValidator.parse('titre-slug-1-for-import')
+  await insertTitreGraph({
+    id: titreId,
+    slug: titreSlug,
+    nom: 'nomTitre',
+    typeId: 'arm',
+    titreStatutId: 'val',
+    propsTitreEtapesIds: {},
+  })
+})
+
+afterAll(async () => {
+  await dbManager.closeKnex()
+})
+
+describe('titres', async () => {
+  test('peut télécharger les titres en csv', async () => {
+    const tested = await restDownloadCall(
+      dbPool,
+      '/titres',
+      {},
+      {
+        role: 'admin',
+        administrationId: ADMINISTRATION_IDS['DGTM - GUYANE'],
+      },
+      { format: 'csv' }
+    )
+
+    expect(tested.text).toMatchInlineSnapshot(`
+      "id,nom,type,domaine,date_debut,date_fin,date_demande,statut,substances,surface renseignee km2,communes (surface calculee km2),forets,facades_maritimes,departements,regions,administrations_noms,titulaires_noms,titulaires_adresses,titulaires_legal,titulaires_categorie,amodiataires_noms,amodiataires_adresses,amodiataires_legal,amodiataires_categorie,geojson
+      titre-slug-1-for-import,nomTitre,autorisation de recherches,minéraux et métaux,,,,valide,,,,,,,,Direction Générale des Territoires et de la Mer de Guyane,,,,,,,,,null"
+    `)
+  })
+  test('peut télécharger les titres en xlsx', async () => {
+    const tested = await restDownloadCall(
+      dbPool,
+      '/titres',
+      {},
+      {
+        role: 'admin',
+        administrationId: ADMINISTRATION_IDS['DGTM - GUYANE'],
+      },
+      { format: 'xlsx' }
+    )
+
+    expect(tested.statusCode).toStrictEqual(HTTP_STATUS.OK)
+  })
+
+  test('peut télécharger les titres en ods', async () => {
+    const tested = await restDownloadCall(
+      dbPool,
+      '/titres',
+      {},
+      {
+        role: 'admin',
+        administrationId: ADMINISTRATION_IDS['DGTM - GUYANE'],
+      },
+      { format: 'ods' }
+    )
+
+    expect(tested.statusCode).toStrictEqual(HTTP_STATUS.OK)
+  })
+
+  test('peut télécharger les titres en geojson', async () => {
+    const tested = await restDownloadCall(
+      dbPool,
+      '/titres',
+      {},
+      {
+        role: 'admin',
+        administrationId: ADMINISTRATION_IDS['DGTM - GUYANE'],
+      },
+      { format: 'geojson' }
+    )
+
+    expect(tested.body).toMatchInlineSnapshot(`
+        {
+          "features": [],
+          "type": "FeatureCollection",
+        }
+      `)
+  })
+})