diff --git a/app/controllers/admin/university/apps_controller.rb b/app/controllers/admin/university/apps_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7f1bf3d0de7470bec9d5ece7d2176a417c586391
--- /dev/null
+++ b/app/controllers/admin/university/apps_controller.rb
@@ -0,0 +1,64 @@
+class Admin::University::AppsController < Admin::University::ApplicationController
+  load_and_authorize_resource class: University::App,
+                              through: :current_university,
+                              through_association: :apps
+
+  def index
+    @apps = apply_scopes(@apps).ordered.page(params[:page])
+    breadcrumb
+  end
+
+  def show
+    breadcrumb
+  end
+
+  def new
+    breadcrumb
+  end
+
+  def edit
+    breadcrumb
+    add_breadcrumb t('edit')
+  end
+
+  def create
+    if @app.save
+      redirect_to admin_university_app_path(@app),
+                  notice: t('admin.successfully_created_html', model: @app.to_s)
+    else
+      breadcrumb
+      render :new, status: :unprocessable_entity
+    end
+  end
+
+  def update
+    if @app.update(app_params)
+      redirect_to admin_university_app_path(@app),
+                  notice: t('admin.successfully_updated_html', model: @app.to_s)
+    else
+      breadcrumb
+      add_breadcrumb t('edit')
+    end
+  end
+
+  def destroy
+    @app.destroy
+    redirect_to admin_university_apps_url,
+                notice: t('admin.successfully_destroyed_html', model: @app.to_s)
+  end
+
+  protected
+
+  def breadcrumb
+    super
+    add_breadcrumb  University::App.model_name.human(count: 2),
+                    admin_university_apps_path
+    breadcrumb_for @app
+  end
+
+  def app_params
+    params.require(:university_app)
+          .permit(:name)
+          .merge(university_id: current_university.id)
+  end
+end
\ No newline at end of file
diff --git a/app/models/university.rb b/app/models/university.rb
index 783967bd869c6ae216961b3ec9f10e7626f21adc..2789a655b08f108b736ea9a3e72e1e65db3358dd 100644
--- a/app/models/university.rb
+++ b/app/models/university.rb
@@ -56,6 +56,7 @@ class University < ApplicationRecord
   # We use after_destroy to let the attachment go first
   has_many :active_storage_blobs, class_name: 'ActiveStorage::Blob'
   has_many :imports, dependent: :destroy
+  has_many :apps, dependent: :destroy
   belongs_to :default_language, class_name: "Language"
 
   validates_presence_of :name
diff --git a/app/models/university/app.rb b/app/models/university/app.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f3f4eab048dc5695dd95e191ad62749aaed7b9ae
--- /dev/null
+++ b/app/models/university/app.rb
@@ -0,0 +1,36 @@
+# == Schema Information
+#
+# Table name: university_apps
+#
+#  id            :uuid             not null, primary key
+#  name          :string
+#  token         :string
+#  created_at    :datetime         not null
+#  updated_at    :datetime         not null
+#  university_id :uuid             not null, indexed
+#
+# Indexes
+#
+#  index_university_apps_on_university_id  (university_id)
+#
+# Foreign Keys
+#
+#  fk_rails_2d07655e23  (university_id => universities.id)
+#
+class University::App < ApplicationRecord
+  include WithUniversity
+
+  scope :ordered, -> { order(:name) }
+
+  before_validation :generate_token
+
+  def to_s
+    "#{name}"
+  end
+
+  protected
+
+  def generate_token
+    self.token = SecureRandom.uuid if self.token.blank?
+  end
+end
diff --git a/app/views/admin/university/apps/_form.html.erb b/app/views/admin/university/apps/_form.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..2d99fdf5ef184f84ddec7e1b7361e0d70e26b857
--- /dev/null
+++ b/app/views/admin/university/apps/_form.html.erb
@@ -0,0 +1,10 @@
+<%= simple_form_for [:admin, app] do |f| %>
+  <%= f.error_notification %>
+  <%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
+
+  <%= f.input :name %>
+
+  <% content_for :action_bar_right do %>
+    <%= submit f %>
+  <% end %>
+<% end %>
diff --git a/app/views/admin/university/apps/_list.html.erb b/app/views/admin/university/apps/_list.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..dac7abf24e89b47e09dcf5049c7b0eed199239aa
--- /dev/null
+++ b/app/views/admin/university/apps/_list.html.erb
@@ -0,0 +1,23 @@
+<div class="table-responsive">
+  <table class="<%= table_classes %>">
+    <thead>
+      <tr>
+        <th><%= University::App.human_attribute_name('name') %></th>
+        <th></th>
+      </tr>
+    </thead>
+    <tbody>
+      <% apps.each do |app| %>
+        <tr>
+          <td><%= link_to app, admin_university_app_path(app) %></td>
+          <td class="text-end">
+            <div class="btn-group" role="group">
+              <%= edit_link app %>
+              <%= destroy_link app %>
+            </div>
+          </td>
+        </tr>
+      <% end %>
+    </tbody>
+  </table>
+</div>
diff --git a/app/views/admin/university/apps/edit.html.erb b/app/views/admin/university/apps/edit.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..75e77d2eac6e9ff041e6bb2d13ae5a809060209c
--- /dev/null
+++ b/app/views/admin/university/apps/edit.html.erb
@@ -0,0 +1,3 @@
+<% content_for :title, @app %>
+
+<%= render 'form', app: @app %>
diff --git a/app/views/admin/university/apps/index.html.erb b/app/views/admin/university/apps/index.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..47be60d351f12117bb747579dd7621b05fd57477
--- /dev/null
+++ b/app/views/admin/university/apps/index.html.erb
@@ -0,0 +1,14 @@
+<% content_for :title, University::App.model_name.human(count: 2) %>
+
+<%
+action = ''
+action += link_to t('create'),
+                  new_admin_university_app_path,
+                  class: button_classes if can?(:create, University::App)
+subtitle = t('admin.elements', count: @apps.total_count)
+%>
+<%= osuny_panel University::App.model_name.human(count: 2), subtitle: subtitle, action: action do %>
+  <%= render 'filters', current_path: admin_university_apps_path, filters: @filters if @filters.any?  %>
+  <%= render 'admin/university/apps/list', apps: @apps %>
+  <%= paginate @apps, theme: 'bootstrap-5' %>
+<% end %>
diff --git a/app/views/admin/university/apps/new.html.erb b/app/views/admin/university/apps/new.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..f2d7dae9625c3b921b69aee42a58881b46637c7c
--- /dev/null
+++ b/app/views/admin/university/apps/new.html.erb
@@ -0,0 +1,3 @@
+<% content_for :title, University::App.model_name.human %>
+
+<%= render 'form', app: @app %>
diff --git a/app/views/admin/university/apps/show.html.erb b/app/views/admin/university/apps/show.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..56d237ac657342ac3e5125fdcdda796f67d21265
--- /dev/null
+++ b/app/views/admin/university/apps/show.html.erb
@@ -0,0 +1,7 @@
+<% content_for :title, @app %>
+
+<%= @app.token %>
+
+<% content_for :action_bar_right do %>
+  <%= edit_link @app %>
+<% end %>
diff --git a/config/locales/university/en.yml b/config/locales/university/en.yml
index 2c134393a3a608622f7b72ef6f1db8ba3e6579dc..3eb6096b1a365db9522e8efcee1b84e4fa90beee 100644
--- a/config/locales/university/en.yml
+++ b/config/locales/university/en.yml
@@ -24,6 +24,9 @@ en:
         sso_target_url: Target URL
         url: URL
         zipcode: Zipcode
+      university/app:
+        name: Name
+        token: Secret token
       university/organization:
         address: Address
         address_name: Address name
@@ -128,6 +131,9 @@ en:
       university:
         one: University
         other: Universities
+      university/app:
+        one: App
+        other: Apps
       university/person:
         one: Person
         other: People
diff --git a/config/locales/university/fr.yml b/config/locales/university/fr.yml
index c88446772c0bb3e42008c3d87b8f0cc0466f54f8..b255321a9d35b9867df8375faa3488689d259f48 100644
--- a/config/locales/university/fr.yml
+++ b/config/locales/university/fr.yml
@@ -24,6 +24,9 @@ fr:
         sso_target_url: URL cible
         url: 'URL'
         zipcode: Code postal
+      university/app:
+        name: Nom
+        token: Jeton secret
       university/organization:
         address: Adresse
         address_name: Nom de l'adresse
@@ -128,6 +131,9 @@ fr:
       university:
         one: Université
         other: Universités
+      university/app:
+        one: App
+        other: Apps
       university/person:
         one: Personne
         other: Personnes
diff --git a/config/routes/admin/university.rb b/config/routes/admin/university.rb
index 10d8c533ac62025ac1d2e7a9e773f3a78ca7b09a..2ad528dc0e888eccd1d51456bfeb1f80facd3b90 100644
--- a/config/routes/admin/university.rb
+++ b/config/routes/admin/university.rb
@@ -8,6 +8,7 @@ namespace :university do
       resources :imports, only: [:index, :show, :new, :create]
     end
   end
+  resources :apps
   resources :alumni, only: [:index, :show] do
     member do
       get 'cohorts' => 'alumni/cohorts#edit'
diff --git a/db/migrate/20230917145029_create_university_applications.rb b/db/migrate/20230917145029_create_university_applications.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d53e7416f32c0f2fe3848c83e5d3d75dea89341f
--- /dev/null
+++ b/db/migrate/20230917145029_create_university_applications.rb
@@ -0,0 +1,11 @@
+class CreateUniversityApplications < ActiveRecord::Migration[7.0]
+  def change
+    create_table :university_apps, id: :uuid do |t|
+      t.string :name
+      t.references :university, null: false, foreign_key: true, type: :uuid
+      t.string :token
+
+      t.timestamps
+    end
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 3e8dc7af3adc319cb87945af495598ef110547d5..9a72f67a1271f4b52edac724dfae61a9f2fd7b0d 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema[7.0].define(version: 2023_09_14_101635) do
+ActiveRecord::Schema[7.0].define(version: 2023_09_17_145029) do
   # These are extensions that must be enabled in order to support this database
   enable_extension "pgcrypto"
   enable_extension "plpgsql"
@@ -969,6 +969,15 @@ ActiveRecord::Schema[7.0].define(version: 2023_09_14_101635) do
     t.index ["default_language_id"], name: "index_universities_on_default_language_id"
   end
 
+  create_table "university_apps", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
+    t.string "name"
+    t.uuid "university_id", null: false
+    t.string "token"
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.index ["university_id"], name: "index_university_apps_on_university_id"
+  end
+
   create_table "university_organization_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
     t.string "name"
     t.uuid "university_id", null: false
@@ -1281,6 +1290,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_09_14_101635) do
   add_foreign_key "research_theses", "university_people", column: "author_id"
   add_foreign_key "research_theses", "university_people", column: "director_id"
   add_foreign_key "universities", "languages", column: "default_language_id"
+  add_foreign_key "university_apps", "universities"
   add_foreign_key "university_organization_categories", "universities"
   add_foreign_key "university_organizations", "languages"
   add_foreign_key "university_organizations", "universities"
diff --git a/test/fixtures/university/apps.yml b/test/fixtures/university/apps.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b65041330b0bbff44ca7ea59f9de68482a4738b3
--- /dev/null
+++ b/test/fixtures/university/apps.yml
@@ -0,0 +1,29 @@
+# == Schema Information
+#
+# Table name: university_apps
+#
+#  id            :uuid             not null, primary key
+#  name          :string
+#  token         :string
+#  created_at    :datetime         not null
+#  updated_at    :datetime         not null
+#  university_id :uuid             not null, indexed
+#
+# Indexes
+#
+#  index_university_apps_on_university_id  (university_id)
+#
+# Foreign Keys
+#
+#  fk_rails_2d07655e23  (university_id => universities.id)
+#
+
+one:
+  name: MyString
+  university: one
+  token: MyString
+
+two:
+  name: MyString
+  university: two
+  token: MyString
diff --git a/test/models/university/app_test.rb b/test/models/university/app_test.rb
new file mode 100644
index 0000000000000000000000000000000000000000..64cd26e3a0c2d28551f524cd0771470bce5a294a
--- /dev/null
+++ b/test/models/university/app_test.rb
@@ -0,0 +1,26 @@
+# == Schema Information
+#
+# Table name: university_apps
+#
+#  id            :uuid             not null, primary key
+#  name          :string
+#  token         :string
+#  created_at    :datetime         not null
+#  updated_at    :datetime         not null
+#  university_id :uuid             not null, indexed
+#
+# Indexes
+#
+#  index_university_apps_on_university_id  (university_id)
+#
+# Foreign Keys
+#
+#  fk_rails_2d07655e23  (university_id => universities.id)
+#
+require "test_helper"
+
+class University::ApplicationTest < ActiveSupport::TestCase
+  # test "the truth" do
+  #   assert true
+  # end
+end