diff --git a/internal/models/election.go b/internal/models/election.go
new file mode 100644
index 0000000000000000000000000000000000000000..00f4a11fb71c2ac865ef03e2c7b0d9f5d1f5a561
--- /dev/null
+++ b/internal/models/election.go
@@ -0,0 +1,113 @@
+package models
+
+import (
+	"encoding/json"
+	"net/http"
+	"strconv"
+	"strings"
+
+	"forge.grandlyon.com/apoyen/elections/internal/auth"
+)
+
+func (d *DataHandler) HandleElection(w http.ResponseWriter, r *http.Request) {
+	id, _ := strconv.Atoi(strings.TrimPrefix(r.URL.Path, "/api/Election/"))
+	switch method := r.Method; method {
+	case "GET":
+		switch auth.GetLoggedUserTechnical(w, r).Role {
+		case "ADMIN":
+			d.getElectionAdmin(w, r, id)
+		case "CAPTURER", "VISUALIZER":
+			http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
+		default:
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
+		}
+	case "POST":
+		switch auth.GetLoggedUserTechnical(w, r).Role {
+		case "ADMIN":
+			d.postElectionAdmin(w, r)
+		case "CAPTURER", "VISUALIZER":
+			http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
+		default:
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
+		}
+
+	case "PUT":
+		switch auth.GetLoggedUserTechnical(w, r).Role {
+		case "ADMIN":
+			d.putElectionAdmin(w, r, id)
+		case "CAPTURER", "VISUALIZER":
+			http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
+		default:
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
+		}
+	case "DELETE":
+		switch auth.GetLoggedUserTechnical(w, r).Role {
+		case "ADMIN":
+			d.deleteElectionAdmin(w, r, id)
+		case "CAPTURER", "VISUALIZER":
+			http.Error(w, ErrorNotAuthorizeMethodOnRessource, http.StatusMethodNotAllowed)
+		default:
+			http.Error(w, ErrorRoleOfLoggedUser, http.StatusInternalServerError)
+		}
+	default:
+		http.Error(w, "method not allowed", 400)
+	}
+}
+
+func (d *DataHandler) getElectionAdmin(w http.ResponseWriter, r *http.Request, id int) {
+	if id != 0 {
+		var o Election
+		if err := d.db.Preload("Areas").First(&o, id).Error; err != nil {
+			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+			return
+		}
+		json.NewEncoder(w).Encode(o)
+	} else {
+		var o []Election
+		d.db.Preload("Areas").Find(&o)
+		json.NewEncoder(w).Encode(o)
+	}
+}
+
+func (d *DataHandler) postElectionAdmin(w http.ResponseWriter, r *http.Request) {
+	var o Election
+	err := json.NewDecoder(r.Body).Decode(&o)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+	}
+	d.db.Create(&o)
+	d.db.Last(&o)
+	json.NewEncoder(w).Encode(o)
+
+}
+
+func (d *DataHandler) putElectionAdmin(w http.ResponseWriter, r *http.Request, id int) {
+	var o Election
+	if err := d.db.Preload("Areas").First(&o, id).Error; err != nil {
+		http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+		return
+	}
+	var election Election
+	err := json.NewDecoder(r.Body).Decode(&election)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+	}
+	o.Name = election.Name
+	o.BallotType = election.BallotType
+	d.db.Save(&o)
+	json.NewEncoder(w).Encode(o)
+
+}
+
+func (d *DataHandler) deleteElectionAdmin(w http.ResponseWriter, r *http.Request, id int) {
+	if id != 0 {
+		var o Election
+		if err := d.db.First(&o, id).Error; err != nil {
+			http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+			return
+		}
+		d.db.Delete(&o)
+	} else {
+		http.Error(w, ErrorIDIsMissing, http.StatusNotFound)
+	}
+}
diff --git a/internal/models/models.go b/internal/models/models.go
index 858791b68c303133d158354ab7e38f6a1ab9af38..e2371675fbda232ee29b0e8fb5bb806ae5cf32c5 100644
--- a/internal/models/models.go
+++ b/internal/models/models.go
@@ -216,6 +216,8 @@ func (d *DataHandler) ProcessAPI(w http.ResponseWriter, r *http.Request) {
 	switch api {
 	case "Capturer":
 		d.HandleCapturer(w, r)
+	case "Election":
+		d.HandleElection(w, r)
 	}
 
 }
diff --git a/internal/rootmux/admin_test.go b/internal/rootmux/admin_test.go
index ba9dc3b2045ff080574b25098862fc99febdc263..12082873dc589318264268f02a9f0f99c677ea51 100644
--- a/internal/rootmux/admin_test.go
+++ b/internal/rootmux/admin_test.go
@@ -33,6 +33,17 @@ func AdminTests(t *testing.T) {
 		// Delete a capturer
 		do("DELETE", "/api/Capturer/3", xsrfHeader, ``, 200, ``)
 
+		// Create an Election
+		do("POST", "/api/Election", xsrfHeader, `{"Name":"Grand Lyon 2020", "BallotType":"metropolitan-direct"}`, 200, `{"ID":1,"Name":"Grand Lyon 2020","BallotType":"metropolitan-direct","Areas":null,"Rounds":null}`)
+		// Get the election
+		do("GET", "/api/Election/1", xsrfHeader, ``, 200, `{"ID":1,"Name":"Grand Lyon 2020","BallotType":"metropolitan-direct","Areas":[],"Rounds":null}`)
+		// Get all the elections
+		do("GET", "/api/Election/", xsrfHeader, ``, 200, `[{"ID":1,"Name":"Grand Lyon 2020","BallotType":"metropolitan-direct","Areas":[],"Rounds":null}]`)
+		// Update a election
+		do("PUT", "/api/Election/1", xsrfHeader, `{"ID":1,"Name":"Grand-Lyon 2020", "BallotType":"metropolitan-direct"}`, 200, `{"ID":1,"Name":"Grand-Lyon 2020","BallotType":"metropolitan-direct","Areas":[],"Rounds":null}`)
+		// Delete a election
+		do("DELETE", "/api/Election/1", xsrfHeader, ``, 200, ``)
+
 	}
 	// Do a in memory login with an known admin
 	do("POST", "/Login", noH, `{"login": "admin","password": "password"}`, 200, "")
diff --git a/internal/rootmux/capturer_test.go b/internal/rootmux/capturer_test.go
index 741c7a8a269c7540b783024d381255a7d4d29b4a..0f91790f0e855c02a7d11aee17d07689b522d5a3 100644
--- a/internal/rootmux/capturer_test.go
+++ b/internal/rootmux/capturer_test.go
@@ -35,6 +35,17 @@ func CapturerTests(t *testing.T) {
 		// Delete a capturer should fail with 405
 		do("DELETE", "/api/Capturer/1", xsrfHeader, ``, 405, `You're not authorize to execute this method on this ressource.`)
 
+		// Create an election should fail with 405
+		do("POST", "/api/Election", xsrfHeader, `{"Name":"Grand Lyon 2020", "BallotType":"metropolitan-direct"}`, 405, `You're not authorize to execute this method on this ressource.`)
+		// Get an Election should fail with 405
+		do("GET", "/api/Election/1", xsrfHeader, "", 405, `You're not authorize to execute this method on this ressource.`)
+		// Get all the elections should fail with 405
+		do("GET", "/api/Election/", xsrfHeader, "", 405, `You're not authorize to execute this method on this ressource.`)
+		// Update an election should fail with 405
+		do("PUT", "/api/Election/1", xsrfHeader, `{"Name":"Grand Lyon 2020", "BallotType":"metropolitan-direct"}`, 405, `You're not authorize to execute this method on this ressource.`)
+		// Delete an election should fail with 405
+		do("DELETE", "/api/Election/1", xsrfHeader, ``, 405, `You're not authorize to execute this method on this ressource.`)
+
 	}
 	// Do a in memory login with an known admin
 	do("POST", "/Login", noH, `{"login": "capturer","password": "password"}`, 200, "")
diff --git a/internal/rootmux/visualizer_test.go b/internal/rootmux/visualizer_test.go
index 8a8b94909a0f9481bcc048f041e7ab12787cb46f..08841a72b871f99fad2187b6d258d57978c54b0a 100644
--- a/internal/rootmux/visualizer_test.go
+++ b/internal/rootmux/visualizer_test.go
@@ -33,6 +33,17 @@ func VisualizerTests(t *testing.T) {
 		// Delete a capturer should fail with 405
 		do("DELETE", "/api/Capturer/1", xsrfHeader, ``, 405, `You're not authorize to execute this method on this ressource.`)
 
+		// Create an election should fail with 405
+		do("POST", "/api/Election", xsrfHeader, `{"Name":"Grand Lyon 2020", "BallotType":"metropolitan-direct"}`, 405, `You're not authorize to execute this method on this ressource.`)
+		// Get an Election should fail with 405
+		do("GET", "/api/Election/1", xsrfHeader, "", 405, `You're not authorize to execute this method on this ressource.`)
+		// Get all the elections should fail with 405
+		do("GET", "/api/Election/", xsrfHeader, "", 405, `You're not authorize to execute this method on this ressource.`)
+		// Update an election should fail with 405
+		do("PUT", "/api/Election/1", xsrfHeader, `{"Name":"Grand Lyon 2020", "BallotType":"metropolitan-direct"}`, 405, `You're not authorize to execute this method on this ressource.`)
+		// Delete an election should fail with 405
+		do("DELETE", "/api/Election/1", xsrfHeader, ``, 405, `You're not authorize to execute this method on this ressource.`)
+
 	}
 	// Do a in memory login with an known admin
 	do("POST", "/Login", noH, `{"login": "visualizer","password": "password"}`, 200, "")