diff --git a/pkg/api/oas_client_gen.go b/pkg/api/oas_client_gen.go
index 2ef1dad..714161e 100644
--- a/pkg/api/oas_client_gen.go
+++ b/pkg/api/oas_client_gen.go
@@ -173,6 +173,12 @@ type Invoker interface {
 	//
 	// DELETE /script-policy/{ScriptPolicyID}
 	DeleteScriptPolicy(ctx context.Context, params DeleteScriptPolicyParams) error
+	// GetMap invokes getMap operation.
+	//
+	// Retrieve map with ID.
+	//
+	// GET /maps/{MapID}
+	GetMap(ctx context.Context, params GetMapParams) (*Map, error)
 	// GetMapfix invokes getMapfix operation.
 	//
 	// Retrieve map with ID.
@@ -203,6 +209,12 @@ type Invoker interface {
 	//
 	// GET /mapfixes
 	ListMapfixes(ctx context.Context, params ListMapfixesParams) ([]Mapfix, error)
+	// ListMaps invokes listMaps operation.
+	//
+	// Get list of maps.
+	//
+	// GET /maps
+	ListMaps(ctx context.Context, params ListMapsParams) ([]Map, error)
 	// ListScriptPolicy invokes listScriptPolicy operation.
 	//
 	// Get list of script policies.
@@ -3242,6 +3254,96 @@ func (c *Client) sendDeleteScriptPolicy(ctx context.Context, params DeleteScript
 	return result, nil
 }
 
+// GetMap invokes getMap operation.
+//
+// Retrieve map with ID.
+//
+// GET /maps/{MapID}
+func (c *Client) GetMap(ctx context.Context, params GetMapParams) (*Map, error) {
+	res, err := c.sendGetMap(ctx, params)
+	return res, err
+}
+
+func (c *Client) sendGetMap(ctx context.Context, params GetMapParams) (res *Map, err error) {
+	otelAttrs := []attribute.KeyValue{
+		otelogen.OperationID("getMap"),
+		semconv.HTTPRequestMethodKey.String("GET"),
+		semconv.HTTPRouteKey.String("/maps/{MapID}"),
+	}
+
+	// Run stopwatch.
+	startTime := time.Now()
+	defer func() {
+		// Use floating point division here for higher precision (instead of Millisecond method).
+		elapsedDuration := time.Since(startTime)
+		c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...))
+	}()
+
+	// Increment request counter.
+	c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...))
+
+	// Start a span for this request.
+	ctx, span := c.cfg.Tracer.Start(ctx, GetMapOperation,
+		trace.WithAttributes(otelAttrs...),
+		clientSpanKind,
+	)
+	// Track stage for error reporting.
+	var stage string
+	defer func() {
+		if err != nil {
+			span.RecordError(err)
+			span.SetStatus(codes.Error, stage)
+			c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...))
+		}
+		span.End()
+	}()
+
+	stage = "BuildURL"
+	u := uri.Clone(c.requestURL(ctx))
+	var pathParts [2]string
+	pathParts[0] = "/maps/"
+	{
+		// Encode "MapID" parameter.
+		e := uri.NewPathEncoder(uri.PathEncoderConfig{
+			Param:   "MapID",
+			Style:   uri.PathStyleSimple,
+			Explode: false,
+		})
+		if err := func() error {
+			return e.EncodeValue(conv.Int64ToString(params.MapID))
+		}(); err != nil {
+			return res, errors.Wrap(err, "encode path")
+		}
+		encoded, err := e.Result()
+		if err != nil {
+			return res, errors.Wrap(err, "encode path")
+		}
+		pathParts[1] = encoded
+	}
+	uri.AddPathParts(u, pathParts[:]...)
+
+	stage = "EncodeRequest"
+	r, err := ht.NewRequest(ctx, "GET", u)
+	if err != nil {
+		return res, errors.Wrap(err, "create request")
+	}
+
+	stage = "SendRequest"
+	resp, err := c.cfg.Client.Do(r)
+	if err != nil {
+		return res, errors.Wrap(err, "do request")
+	}
+	defer resp.Body.Close()
+
+	stage = "DecodeResponse"
+	result, err := decodeGetMapResponse(resp)
+	if err != nil {
+		return res, errors.Wrap(err, "decode response")
+	}
+
+	return result, nil
+}
+
 // GetMapfix invokes getMapfix operation.
 //
 // Retrieve map with ID.
@@ -3774,6 +3876,178 @@ func (c *Client) sendListMapfixes(ctx context.Context, params ListMapfixesParams
 	return result, nil
 }
 
+// ListMaps invokes listMaps operation.
+//
+// Get list of maps.
+//
+// GET /maps
+func (c *Client) ListMaps(ctx context.Context, params ListMapsParams) ([]Map, error) {
+	res, err := c.sendListMaps(ctx, params)
+	return res, err
+}
+
+func (c *Client) sendListMaps(ctx context.Context, params ListMapsParams) (res []Map, err error) {
+	otelAttrs := []attribute.KeyValue{
+		otelogen.OperationID("listMaps"),
+		semconv.HTTPRequestMethodKey.String("GET"),
+		semconv.HTTPRouteKey.String("/maps"),
+	}
+
+	// Run stopwatch.
+	startTime := time.Now()
+	defer func() {
+		// Use floating point division here for higher precision (instead of Millisecond method).
+		elapsedDuration := time.Since(startTime)
+		c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...))
+	}()
+
+	// Increment request counter.
+	c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...))
+
+	// Start a span for this request.
+	ctx, span := c.cfg.Tracer.Start(ctx, ListMapsOperation,
+		trace.WithAttributes(otelAttrs...),
+		clientSpanKind,
+	)
+	// Track stage for error reporting.
+	var stage string
+	defer func() {
+		if err != nil {
+			span.RecordError(err)
+			span.SetStatus(codes.Error, stage)
+			c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...))
+		}
+		span.End()
+	}()
+
+	stage = "BuildURL"
+	u := uri.Clone(c.requestURL(ctx))
+	var pathParts [1]string
+	pathParts[0] = "/maps"
+	uri.AddPathParts(u, pathParts[:]...)
+
+	stage = "EncodeQueryParams"
+	q := uri.NewQueryEncoder()
+	{
+		// Encode "Page" parameter.
+		cfg := uri.QueryParameterEncodingConfig{
+			Name:    "Page",
+			Style:   uri.QueryStyleForm,
+			Explode: true,
+		}
+
+		if err := q.EncodeParam(cfg, func(e uri.Encoder) error {
+			return e.EncodeValue(conv.Int32ToString(params.Page))
+		}); err != nil {
+			return res, errors.Wrap(err, "encode query")
+		}
+	}
+	{
+		// Encode "Limit" parameter.
+		cfg := uri.QueryParameterEncodingConfig{
+			Name:    "Limit",
+			Style:   uri.QueryStyleForm,
+			Explode: true,
+		}
+
+		if err := q.EncodeParam(cfg, func(e uri.Encoder) error {
+			return e.EncodeValue(conv.Int32ToString(params.Limit))
+		}); err != nil {
+			return res, errors.Wrap(err, "encode query")
+		}
+	}
+	{
+		// Encode "DisplayName" parameter.
+		cfg := uri.QueryParameterEncodingConfig{
+			Name:    "DisplayName",
+			Style:   uri.QueryStyleForm,
+			Explode: true,
+		}
+
+		if err := q.EncodeParam(cfg, func(e uri.Encoder) error {
+			if val, ok := params.DisplayName.Get(); ok {
+				return e.EncodeValue(conv.StringToString(val))
+			}
+			return nil
+		}); err != nil {
+			return res, errors.Wrap(err, "encode query")
+		}
+	}
+	{
+		// Encode "Creator" parameter.
+		cfg := uri.QueryParameterEncodingConfig{
+			Name:    "Creator",
+			Style:   uri.QueryStyleForm,
+			Explode: true,
+		}
+
+		if err := q.EncodeParam(cfg, func(e uri.Encoder) error {
+			if val, ok := params.Creator.Get(); ok {
+				return e.EncodeValue(conv.StringToString(val))
+			}
+			return nil
+		}); err != nil {
+			return res, errors.Wrap(err, "encode query")
+		}
+	}
+	{
+		// Encode "GameID" parameter.
+		cfg := uri.QueryParameterEncodingConfig{
+			Name:    "GameID",
+			Style:   uri.QueryStyleForm,
+			Explode: true,
+		}
+
+		if err := q.EncodeParam(cfg, func(e uri.Encoder) error {
+			if val, ok := params.GameID.Get(); ok {
+				return e.EncodeValue(conv.Int32ToString(val))
+			}
+			return nil
+		}); err != nil {
+			return res, errors.Wrap(err, "encode query")
+		}
+	}
+	{
+		// Encode "Sort" parameter.
+		cfg := uri.QueryParameterEncodingConfig{
+			Name:    "Sort",
+			Style:   uri.QueryStyleForm,
+			Explode: true,
+		}
+
+		if err := q.EncodeParam(cfg, func(e uri.Encoder) error {
+			if val, ok := params.Sort.Get(); ok {
+				return e.EncodeValue(conv.Int32ToString(val))
+			}
+			return nil
+		}); err != nil {
+			return res, errors.Wrap(err, "encode query")
+		}
+	}
+	u.RawQuery = q.Values().Encode()
+
+	stage = "EncodeRequest"
+	r, err := ht.NewRequest(ctx, "GET", u)
+	if err != nil {
+		return res, errors.Wrap(err, "create request")
+	}
+
+	stage = "SendRequest"
+	resp, err := c.cfg.Client.Do(r)
+	if err != nil {
+		return res, errors.Wrap(err, "do request")
+	}
+	defer resp.Body.Close()
+
+	stage = "DecodeResponse"
+	result, err := decodeListMapsResponse(resp)
+	if err != nil {
+		return res, errors.Wrap(err, "decode response")
+	}
+
+	return result, nil
+}
+
 // ListScriptPolicy invokes listScriptPolicy operation.
 //
 // Get list of script policies.
diff --git a/pkg/api/oas_handlers_gen.go b/pkg/api/oas_handlers_gen.go
index e7f8893..95e1799 100644
--- a/pkg/api/oas_handlers_gen.go
+++ b/pkg/api/oas_handlers_gen.go
@@ -4710,6 +4710,155 @@ func (s *Server) handleDeleteScriptPolicyRequest(args [1]string, argsEscaped boo
 	}
 }
 
+// handleGetMapRequest handles getMap operation.
+//
+// Retrieve map with ID.
+//
+// GET /maps/{MapID}
+func (s *Server) handleGetMapRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
+	statusWriter := &codeRecorder{ResponseWriter: w}
+	w = statusWriter
+	otelAttrs := []attribute.KeyValue{
+		otelogen.OperationID("getMap"),
+		semconv.HTTPRequestMethodKey.String("GET"),
+		semconv.HTTPRouteKey.String("/maps/{MapID}"),
+	}
+
+	// Start a span for this request.
+	ctx, span := s.cfg.Tracer.Start(r.Context(), GetMapOperation,
+		trace.WithAttributes(otelAttrs...),
+		serverSpanKind,
+	)
+	defer span.End()
+
+	// Add Labeler to context.
+	labeler := &Labeler{attrs: otelAttrs}
+	ctx = contextWithLabeler(ctx, labeler)
+
+	// Run stopwatch.
+	startTime := time.Now()
+	defer func() {
+		elapsedDuration := time.Since(startTime)
+
+		attrSet := labeler.AttributeSet()
+		attrs := attrSet.ToSlice()
+		code := statusWriter.status
+		if code != 0 {
+			codeAttr := semconv.HTTPResponseStatusCode(code)
+			attrs = append(attrs, codeAttr)
+			span.SetAttributes(codeAttr)
+		}
+		attrOpt := metric.WithAttributes(attrs...)
+
+		// Increment request counter.
+		s.requests.Add(ctx, 1, attrOpt)
+
+		// Use floating point division here for higher precision (instead of Millisecond method).
+		s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
+	}()
+
+	var (
+		recordError = func(stage string, err error) {
+			span.RecordError(err)
+
+			// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
+			// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
+			// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
+			// max redirects exceeded), in which case status MUST be set to Error.
+			code := statusWriter.status
+			if code >= 100 && code < 500 {
+				span.SetStatus(codes.Error, stage)
+			}
+
+			attrSet := labeler.AttributeSet()
+			attrs := attrSet.ToSlice()
+			if code != 0 {
+				attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
+			}
+
+			s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
+		}
+		err          error
+		opErrContext = ogenerrors.OperationContext{
+			Name: GetMapOperation,
+			ID:   "getMap",
+		}
+	)
+	params, err := decodeGetMapParams(args, argsEscaped, r)
+	if err != nil {
+		err = &ogenerrors.DecodeParamsError{
+			OperationContext: opErrContext,
+			Err:              err,
+		}
+		defer recordError("DecodeParams", err)
+		s.cfg.ErrorHandler(ctx, w, r, err)
+		return
+	}
+
+	var response *Map
+	if m := s.cfg.Middleware; m != nil {
+		mreq := middleware.Request{
+			Context:          ctx,
+			OperationName:    GetMapOperation,
+			OperationSummary: "Retrieve map with ID",
+			OperationID:      "getMap",
+			Body:             nil,
+			Params: middleware.Parameters{
+				{
+					Name: "MapID",
+					In:   "path",
+				}: params.MapID,
+			},
+			Raw: r,
+		}
+
+		type (
+			Request  = struct{}
+			Params   = GetMapParams
+			Response = *Map
+		)
+		response, err = middleware.HookMiddleware[
+			Request,
+			Params,
+			Response,
+		](
+			m,
+			mreq,
+			unpackGetMapParams,
+			func(ctx context.Context, request Request, params Params) (response Response, err error) {
+				response, err = s.h.GetMap(ctx, params)
+				return response, err
+			},
+		)
+	} else {
+		response, err = s.h.GetMap(ctx, params)
+	}
+	if err != nil {
+		if errRes, ok := errors.Into[*ErrorStatusCode](err); ok {
+			if err := encodeErrorResponse(errRes, w, span); err != nil {
+				defer recordError("Internal", err)
+			}
+			return
+		}
+		if errors.Is(err, ht.ErrNotImplemented) {
+			s.cfg.ErrorHandler(ctx, w, r, err)
+			return
+		}
+		if err := encodeErrorResponse(s.h.NewError(ctx, err), w, span); err != nil {
+			defer recordError("Internal", err)
+		}
+		return
+	}
+
+	if err := encodeGetMapResponse(response, w, span); err != nil {
+		defer recordError("EncodeResponse", err)
+		if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
+			s.cfg.ErrorHandler(ctx, w, r, err)
+		}
+		return
+	}
+}
+
 // handleGetMapfixRequest handles getMapfix operation.
 //
 // Retrieve map with ID.
@@ -5475,6 +5624,175 @@ func (s *Server) handleListMapfixesRequest(args [0]string, argsEscaped bool, w h
 	}
 }
 
+// handleListMapsRequest handles listMaps operation.
+//
+// Get list of maps.
+//
+// GET /maps
+func (s *Server) handleListMapsRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
+	statusWriter := &codeRecorder{ResponseWriter: w}
+	w = statusWriter
+	otelAttrs := []attribute.KeyValue{
+		otelogen.OperationID("listMaps"),
+		semconv.HTTPRequestMethodKey.String("GET"),
+		semconv.HTTPRouteKey.String("/maps"),
+	}
+
+	// Start a span for this request.
+	ctx, span := s.cfg.Tracer.Start(r.Context(), ListMapsOperation,
+		trace.WithAttributes(otelAttrs...),
+		serverSpanKind,
+	)
+	defer span.End()
+
+	// Add Labeler to context.
+	labeler := &Labeler{attrs: otelAttrs}
+	ctx = contextWithLabeler(ctx, labeler)
+
+	// Run stopwatch.
+	startTime := time.Now()
+	defer func() {
+		elapsedDuration := time.Since(startTime)
+
+		attrSet := labeler.AttributeSet()
+		attrs := attrSet.ToSlice()
+		code := statusWriter.status
+		if code != 0 {
+			codeAttr := semconv.HTTPResponseStatusCode(code)
+			attrs = append(attrs, codeAttr)
+			span.SetAttributes(codeAttr)
+		}
+		attrOpt := metric.WithAttributes(attrs...)
+
+		// Increment request counter.
+		s.requests.Add(ctx, 1, attrOpt)
+
+		// Use floating point division here for higher precision (instead of Millisecond method).
+		s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
+	}()
+
+	var (
+		recordError = func(stage string, err error) {
+			span.RecordError(err)
+
+			// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
+			// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
+			// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
+			// max redirects exceeded), in which case status MUST be set to Error.
+			code := statusWriter.status
+			if code >= 100 && code < 500 {
+				span.SetStatus(codes.Error, stage)
+			}
+
+			attrSet := labeler.AttributeSet()
+			attrs := attrSet.ToSlice()
+			if code != 0 {
+				attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
+			}
+
+			s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
+		}
+		err          error
+		opErrContext = ogenerrors.OperationContext{
+			Name: ListMapsOperation,
+			ID:   "listMaps",
+		}
+	)
+	params, err := decodeListMapsParams(args, argsEscaped, r)
+	if err != nil {
+		err = &ogenerrors.DecodeParamsError{
+			OperationContext: opErrContext,
+			Err:              err,
+		}
+		defer recordError("DecodeParams", err)
+		s.cfg.ErrorHandler(ctx, w, r, err)
+		return
+	}
+
+	var response []Map
+	if m := s.cfg.Middleware; m != nil {
+		mreq := middleware.Request{
+			Context:          ctx,
+			OperationName:    ListMapsOperation,
+			OperationSummary: "Get list of maps",
+			OperationID:      "listMaps",
+			Body:             nil,
+			Params: middleware.Parameters{
+				{
+					Name: "Page",
+					In:   "query",
+				}: params.Page,
+				{
+					Name: "Limit",
+					In:   "query",
+				}: params.Limit,
+				{
+					Name: "DisplayName",
+					In:   "query",
+				}: params.DisplayName,
+				{
+					Name: "Creator",
+					In:   "query",
+				}: params.Creator,
+				{
+					Name: "GameID",
+					In:   "query",
+				}: params.GameID,
+				{
+					Name: "Sort",
+					In:   "query",
+				}: params.Sort,
+			},
+			Raw: r,
+		}
+
+		type (
+			Request  = struct{}
+			Params   = ListMapsParams
+			Response = []Map
+		)
+		response, err = middleware.HookMiddleware[
+			Request,
+			Params,
+			Response,
+		](
+			m,
+			mreq,
+			unpackListMapsParams,
+			func(ctx context.Context, request Request, params Params) (response Response, err error) {
+				response, err = s.h.ListMaps(ctx, params)
+				return response, err
+			},
+		)
+	} else {
+		response, err = s.h.ListMaps(ctx, params)
+	}
+	if err != nil {
+		if errRes, ok := errors.Into[*ErrorStatusCode](err); ok {
+			if err := encodeErrorResponse(errRes, w, span); err != nil {
+				defer recordError("Internal", err)
+			}
+			return
+		}
+		if errors.Is(err, ht.ErrNotImplemented) {
+			s.cfg.ErrorHandler(ctx, w, r, err)
+			return
+		}
+		if err := encodeErrorResponse(s.h.NewError(ctx, err), w, span); err != nil {
+			defer recordError("Internal", err)
+		}
+		return
+	}
+
+	if err := encodeListMapsResponse(response, w, span); err != nil {
+		defer recordError("EncodeResponse", err)
+		if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
+			s.cfg.ErrorHandler(ctx, w, r, err)
+		}
+		return
+	}
+}
+
 // handleListScriptPolicyRequest handles listScriptPolicy operation.
 //
 // Get list of script policies.
diff --git a/pkg/api/oas_json_gen.go b/pkg/api/oas_json_gen.go
index bb97445..9061475 100644
--- a/pkg/api/oas_json_gen.go
+++ b/pkg/api/oas_json_gen.go
@@ -222,6 +222,170 @@ func (s *ID) UnmarshalJSON(data []byte) error {
 	return s.Decode(d)
 }
 
+// Encode implements json.Marshaler.
+func (s *Map) Encode(e *jx.Encoder) {
+	e.ObjStart()
+	s.encodeFields(e)
+	e.ObjEnd()
+}
+
+// encodeFields encodes fields.
+func (s *Map) encodeFields(e *jx.Encoder) {
+	{
+		e.FieldStart("ID")
+		e.Int64(s.ID)
+	}
+	{
+		e.FieldStart("DisplayName")
+		e.Str(s.DisplayName)
+	}
+	{
+		e.FieldStart("Creator")
+		e.Str(s.Creator)
+	}
+	{
+		e.FieldStart("GameID")
+		e.Int32(s.GameID)
+	}
+	{
+		e.FieldStart("Date")
+		e.Int64(s.Date)
+	}
+}
+
+var jsonFieldsNameOfMap = [5]string{
+	0: "ID",
+	1: "DisplayName",
+	2: "Creator",
+	3: "GameID",
+	4: "Date",
+}
+
+// Decode decodes Map from json.
+func (s *Map) Decode(d *jx.Decoder) error {
+	if s == nil {
+		return errors.New("invalid: unable to decode Map to nil")
+	}
+	var requiredBitSet [1]uint8
+
+	if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error {
+		switch string(k) {
+		case "ID":
+			requiredBitSet[0] |= 1 << 0
+			if err := func() error {
+				v, err := d.Int64()
+				s.ID = int64(v)
+				if err != nil {
+					return err
+				}
+				return nil
+			}(); err != nil {
+				return errors.Wrap(err, "decode field \"ID\"")
+			}
+		case "DisplayName":
+			requiredBitSet[0] |= 1 << 1
+			if err := func() error {
+				v, err := d.Str()
+				s.DisplayName = string(v)
+				if err != nil {
+					return err
+				}
+				return nil
+			}(); err != nil {
+				return errors.Wrap(err, "decode field \"DisplayName\"")
+			}
+		case "Creator":
+			requiredBitSet[0] |= 1 << 2
+			if err := func() error {
+				v, err := d.Str()
+				s.Creator = string(v)
+				if err != nil {
+					return err
+				}
+				return nil
+			}(); err != nil {
+				return errors.Wrap(err, "decode field \"Creator\"")
+			}
+		case "GameID":
+			requiredBitSet[0] |= 1 << 3
+			if err := func() error {
+				v, err := d.Int32()
+				s.GameID = int32(v)
+				if err != nil {
+					return err
+				}
+				return nil
+			}(); err != nil {
+				return errors.Wrap(err, "decode field \"GameID\"")
+			}
+		case "Date":
+			requiredBitSet[0] |= 1 << 4
+			if err := func() error {
+				v, err := d.Int64()
+				s.Date = int64(v)
+				if err != nil {
+					return err
+				}
+				return nil
+			}(); err != nil {
+				return errors.Wrap(err, "decode field \"Date\"")
+			}
+		default:
+			return d.Skip()
+		}
+		return nil
+	}); err != nil {
+		return errors.Wrap(err, "decode Map")
+	}
+	// Validate required fields.
+	var failures []validate.FieldError
+	for i, mask := range [1]uint8{
+		0b00011111,
+	} {
+		if result := (requiredBitSet[i] & mask) ^ mask; result != 0 {
+			// Mask only required fields and check equality to mask using XOR.
+			//
+			// If XOR result is not zero, result is not equal to expected, so some fields are missed.
+			// Bits of fields which would be set are actually bits of missed fields.
+			missed := bits.OnesCount8(result)
+			for bitN := 0; bitN < missed; bitN++ {
+				bitIdx := bits.TrailingZeros8(result)
+				fieldIdx := i*8 + bitIdx
+				var name string
+				if fieldIdx < len(jsonFieldsNameOfMap) {
+					name = jsonFieldsNameOfMap[fieldIdx]
+				} else {
+					name = strconv.Itoa(fieldIdx)
+				}
+				failures = append(failures, validate.FieldError{
+					Name:  name,
+					Error: validate.ErrFieldRequired,
+				})
+				// Reset bit.
+				result &^= 1 << bitIdx
+			}
+		}
+	}
+	if len(failures) > 0 {
+		return &validate.Error{Fields: failures}
+	}
+
+	return nil
+}
+
+// MarshalJSON implements stdjson.Marshaler.
+func (s *Map) MarshalJSON() ([]byte, error) {
+	e := jx.Encoder{}
+	s.Encode(&e)
+	return e.Bytes(), nil
+}
+
+// UnmarshalJSON implements stdjson.Unmarshaler.
+func (s *Map) UnmarshalJSON(data []byte) error {
+	d := jx.DecodeBytes(data)
+	return s.Decode(d)
+}
+
 // Encode implements json.Marshaler.
 func (s *Mapfix) Encode(e *jx.Encoder) {
 	e.ObjStart()
diff --git a/pkg/api/oas_operations_gen.go b/pkg/api/oas_operations_gen.go
index 04127ea..f2235e9 100644
--- a/pkg/api/oas_operations_gen.go
+++ b/pkg/api/oas_operations_gen.go
@@ -30,11 +30,13 @@ const (
 	CreateSubmissionOperation                OperationName = "CreateSubmission"
 	DeleteScriptOperation                    OperationName = "DeleteScript"
 	DeleteScriptPolicyOperation              OperationName = "DeleteScriptPolicy"
+	GetMapOperation                          OperationName = "GetMap"
 	GetMapfixOperation                       OperationName = "GetMapfix"
 	GetScriptOperation                       OperationName = "GetScript"
 	GetScriptPolicyOperation                 OperationName = "GetScriptPolicy"
 	GetSubmissionOperation                   OperationName = "GetSubmission"
 	ListMapfixesOperation                    OperationName = "ListMapfixes"
+	ListMapsOperation                        OperationName = "ListMaps"
 	ListScriptPolicyOperation                OperationName = "ListScriptPolicy"
 	ListScriptsOperation                     OperationName = "ListScripts"
 	ListSubmissionsOperation                 OperationName = "ListSubmissions"
diff --git a/pkg/api/oas_parameters_gen.go b/pkg/api/oas_parameters_gen.go
index 0acb395..6ea7cb4 100644
--- a/pkg/api/oas_parameters_gen.go
+++ b/pkg/api/oas_parameters_gen.go
@@ -1335,6 +1335,72 @@ func decodeDeleteScriptPolicyParams(args [1]string, argsEscaped bool, r *http.Re
 	return params, nil
 }
 
+// GetMapParams is parameters of getMap operation.
+type GetMapParams struct {
+	// The unique identifier for a map.
+	MapID int64
+}
+
+func unpackGetMapParams(packed middleware.Parameters) (params GetMapParams) {
+	{
+		key := middleware.ParameterKey{
+			Name: "MapID",
+			In:   "path",
+		}
+		params.MapID = packed[key].(int64)
+	}
+	return params
+}
+
+func decodeGetMapParams(args [1]string, argsEscaped bool, r *http.Request) (params GetMapParams, _ error) {
+	// Decode path: MapID.
+	if err := func() error {
+		param := args[0]
+		if argsEscaped {
+			unescaped, err := url.PathUnescape(args[0])
+			if err != nil {
+				return errors.Wrap(err, "unescape path")
+			}
+			param = unescaped
+		}
+		if len(param) > 0 {
+			d := uri.NewPathDecoder(uri.PathDecoderConfig{
+				Param:   "MapID",
+				Value:   param,
+				Style:   uri.PathStyleSimple,
+				Explode: false,
+			})
+
+			if err := func() error {
+				val, err := d.DecodeValue()
+				if err != nil {
+					return err
+				}
+
+				c, err := conv.ToInt64(val)
+				if err != nil {
+					return err
+				}
+
+				params.MapID = c
+				return nil
+			}(); err != nil {
+				return err
+			}
+		} else {
+			return validate.ErrFieldRequired
+		}
+		return nil
+	}(); err != nil {
+		return params, &ogenerrors.DecodeParamError{
+			Name: "MapID",
+			In:   "path",
+			Err:  err,
+		}
+	}
+	return params, nil
+}
+
 // GetMapfixParams is parameters of getMapfix operation.
 type GetMapfixParams struct {
 	// The unique identifier for a mapfix.
@@ -1984,6 +2050,391 @@ func decodeListMapfixesParams(args [0]string, argsEscaped bool, r *http.Request)
 	return params, nil
 }
 
+// ListMapsParams is parameters of listMaps operation.
+type ListMapsParams struct {
+	Page        int32
+	Limit       int32
+	DisplayName OptString
+	Creator     OptString
+	GameID      OptInt32
+	Sort        OptInt32
+}
+
+func unpackListMapsParams(packed middleware.Parameters) (params ListMapsParams) {
+	{
+		key := middleware.ParameterKey{
+			Name: "Page",
+			In:   "query",
+		}
+		params.Page = packed[key].(int32)
+	}
+	{
+		key := middleware.ParameterKey{
+			Name: "Limit",
+			In:   "query",
+		}
+		params.Limit = packed[key].(int32)
+	}
+	{
+		key := middleware.ParameterKey{
+			Name: "DisplayName",
+			In:   "query",
+		}
+		if v, ok := packed[key]; ok {
+			params.DisplayName = v.(OptString)
+		}
+	}
+	{
+		key := middleware.ParameterKey{
+			Name: "Creator",
+			In:   "query",
+		}
+		if v, ok := packed[key]; ok {
+			params.Creator = v.(OptString)
+		}
+	}
+	{
+		key := middleware.ParameterKey{
+			Name: "GameID",
+			In:   "query",
+		}
+		if v, ok := packed[key]; ok {
+			params.GameID = v.(OptInt32)
+		}
+	}
+	{
+		key := middleware.ParameterKey{
+			Name: "Sort",
+			In:   "query",
+		}
+		if v, ok := packed[key]; ok {
+			params.Sort = v.(OptInt32)
+		}
+	}
+	return params
+}
+
+func decodeListMapsParams(args [0]string, argsEscaped bool, r *http.Request) (params ListMapsParams, _ error) {
+	q := uri.NewQueryDecoder(r.URL.Query())
+	// Decode query: Page.
+	if err := func() error {
+		cfg := uri.QueryParameterDecodingConfig{
+			Name:    "Page",
+			Style:   uri.QueryStyleForm,
+			Explode: true,
+		}
+
+		if err := q.HasParam(cfg); err == nil {
+			if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
+				val, err := d.DecodeValue()
+				if err != nil {
+					return err
+				}
+
+				c, err := conv.ToInt32(val)
+				if err != nil {
+					return err
+				}
+
+				params.Page = c
+				return nil
+			}); err != nil {
+				return err
+			}
+			if err := func() error {
+				if err := (validate.Int{
+					MinSet:        true,
+					Min:           1,
+					MaxSet:        false,
+					Max:           0,
+					MinExclusive:  false,
+					MaxExclusive:  false,
+					MultipleOfSet: false,
+					MultipleOf:    0,
+				}).Validate(int64(params.Page)); err != nil {
+					return errors.Wrap(err, "int")
+				}
+				return nil
+			}(); err != nil {
+				return err
+			}
+		} else {
+			return err
+		}
+		return nil
+	}(); err != nil {
+		return params, &ogenerrors.DecodeParamError{
+			Name: "Page",
+			In:   "query",
+			Err:  err,
+		}
+	}
+	// Decode query: Limit.
+	if err := func() error {
+		cfg := uri.QueryParameterDecodingConfig{
+			Name:    "Limit",
+			Style:   uri.QueryStyleForm,
+			Explode: true,
+		}
+
+		if err := q.HasParam(cfg); err == nil {
+			if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
+				val, err := d.DecodeValue()
+				if err != nil {
+					return err
+				}
+
+				c, err := conv.ToInt32(val)
+				if err != nil {
+					return err
+				}
+
+				params.Limit = c
+				return nil
+			}); err != nil {
+				return err
+			}
+			if err := func() error {
+				if err := (validate.Int{
+					MinSet:        true,
+					Min:           1,
+					MaxSet:        true,
+					Max:           100,
+					MinExclusive:  false,
+					MaxExclusive:  false,
+					MultipleOfSet: false,
+					MultipleOf:    0,
+				}).Validate(int64(params.Limit)); err != nil {
+					return errors.Wrap(err, "int")
+				}
+				return nil
+			}(); err != nil {
+				return err
+			}
+		} else {
+			return err
+		}
+		return nil
+	}(); err != nil {
+		return params, &ogenerrors.DecodeParamError{
+			Name: "Limit",
+			In:   "query",
+			Err:  err,
+		}
+	}
+	// Decode query: DisplayName.
+	if err := func() error {
+		cfg := uri.QueryParameterDecodingConfig{
+			Name:    "DisplayName",
+			Style:   uri.QueryStyleForm,
+			Explode: true,
+		}
+
+		if err := q.HasParam(cfg); err == nil {
+			if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
+				var paramsDotDisplayNameVal string
+				if err := func() error {
+					val, err := d.DecodeValue()
+					if err != nil {
+						return err
+					}
+
+					c, err := conv.ToString(val)
+					if err != nil {
+						return err
+					}
+
+					paramsDotDisplayNameVal = c
+					return nil
+				}(); err != nil {
+					return err
+				}
+				params.DisplayName.SetTo(paramsDotDisplayNameVal)
+				return nil
+			}); err != nil {
+				return err
+			}
+			if err := func() error {
+				if value, ok := params.DisplayName.Get(); ok {
+					if err := func() error {
+						if err := (validate.String{
+							MinLength:    0,
+							MinLengthSet: false,
+							MaxLength:    128,
+							MaxLengthSet: true,
+							Email:        false,
+							Hostname:     false,
+							Regex:        nil,
+						}).Validate(string(value)); err != nil {
+							return errors.Wrap(err, "string")
+						}
+						return nil
+					}(); err != nil {
+						return err
+					}
+				}
+				return nil
+			}(); err != nil {
+				return err
+			}
+		}
+		return nil
+	}(); err != nil {
+		return params, &ogenerrors.DecodeParamError{
+			Name: "DisplayName",
+			In:   "query",
+			Err:  err,
+		}
+	}
+	// Decode query: Creator.
+	if err := func() error {
+		cfg := uri.QueryParameterDecodingConfig{
+			Name:    "Creator",
+			Style:   uri.QueryStyleForm,
+			Explode: true,
+		}
+
+		if err := q.HasParam(cfg); err == nil {
+			if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
+				var paramsDotCreatorVal string
+				if err := func() error {
+					val, err := d.DecodeValue()
+					if err != nil {
+						return err
+					}
+
+					c, err := conv.ToString(val)
+					if err != nil {
+						return err
+					}
+
+					paramsDotCreatorVal = c
+					return nil
+				}(); err != nil {
+					return err
+				}
+				params.Creator.SetTo(paramsDotCreatorVal)
+				return nil
+			}); err != nil {
+				return err
+			}
+			if err := func() error {
+				if value, ok := params.Creator.Get(); ok {
+					if err := func() error {
+						if err := (validate.String{
+							MinLength:    0,
+							MinLengthSet: false,
+							MaxLength:    128,
+							MaxLengthSet: true,
+							Email:        false,
+							Hostname:     false,
+							Regex:        nil,
+						}).Validate(string(value)); err != nil {
+							return errors.Wrap(err, "string")
+						}
+						return nil
+					}(); err != nil {
+						return err
+					}
+				}
+				return nil
+			}(); err != nil {
+				return err
+			}
+		}
+		return nil
+	}(); err != nil {
+		return params, &ogenerrors.DecodeParamError{
+			Name: "Creator",
+			In:   "query",
+			Err:  err,
+		}
+	}
+	// Decode query: GameID.
+	if err := func() error {
+		cfg := uri.QueryParameterDecodingConfig{
+			Name:    "GameID",
+			Style:   uri.QueryStyleForm,
+			Explode: true,
+		}
+
+		if err := q.HasParam(cfg); err == nil {
+			if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
+				var paramsDotGameIDVal int32
+				if err := func() error {
+					val, err := d.DecodeValue()
+					if err != nil {
+						return err
+					}
+
+					c, err := conv.ToInt32(val)
+					if err != nil {
+						return err
+					}
+
+					paramsDotGameIDVal = c
+					return nil
+				}(); err != nil {
+					return err
+				}
+				params.GameID.SetTo(paramsDotGameIDVal)
+				return nil
+			}); err != nil {
+				return err
+			}
+		}
+		return nil
+	}(); err != nil {
+		return params, &ogenerrors.DecodeParamError{
+			Name: "GameID",
+			In:   "query",
+			Err:  err,
+		}
+	}
+	// Decode query: Sort.
+	if err := func() error {
+		cfg := uri.QueryParameterDecodingConfig{
+			Name:    "Sort",
+			Style:   uri.QueryStyleForm,
+			Explode: true,
+		}
+
+		if err := q.HasParam(cfg); err == nil {
+			if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
+				var paramsDotSortVal int32
+				if err := func() error {
+					val, err := d.DecodeValue()
+					if err != nil {
+						return err
+					}
+
+					c, err := conv.ToInt32(val)
+					if err != nil {
+						return err
+					}
+
+					paramsDotSortVal = c
+					return nil
+				}(); err != nil {
+					return err
+				}
+				params.Sort.SetTo(paramsDotSortVal)
+				return nil
+			}); err != nil {
+				return err
+			}
+		}
+		return nil
+	}(); err != nil {
+		return params, &ogenerrors.DecodeParamError{
+			Name: "Sort",
+			In:   "query",
+			Err:  err,
+		}
+	}
+	return params, nil
+}
+
 // ListScriptPolicyParams is parameters of listScriptPolicy operation.
 type ListScriptPolicyParams struct {
 	Page           int32
diff --git a/pkg/api/oas_response_decoders_gen.go b/pkg/api/oas_response_decoders_gen.go
index 828a516..6a6b258 100644
--- a/pkg/api/oas_response_decoders_gen.go
+++ b/pkg/api/oas_response_decoders_gen.go
@@ -1367,6 +1367,98 @@ func decodeDeleteScriptPolicyResponse(resp *http.Response) (res *DeleteScriptPol
 	return res, errors.Wrap(defRes, "error")
 }
 
+func decodeGetMapResponse(resp *http.Response) (res *Map, _ error) {
+	switch resp.StatusCode {
+	case 200:
+		// Code 200.
+		ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
+		if err != nil {
+			return res, errors.Wrap(err, "parse media type")
+		}
+		switch {
+		case ct == "application/json":
+			buf, err := io.ReadAll(resp.Body)
+			if err != nil {
+				return res, err
+			}
+			d := jx.DecodeBytes(buf)
+
+			var response Map
+			if err := func() error {
+				if err := response.Decode(d); err != nil {
+					return err
+				}
+				if err := d.Skip(); err != io.EOF {
+					return errors.New("unexpected trailing data")
+				}
+				return nil
+			}(); err != nil {
+				err = &ogenerrors.DecodeBodyError{
+					ContentType: ct,
+					Body:        buf,
+					Err:         err,
+				}
+				return res, err
+			}
+			// Validate response.
+			if err := func() error {
+				if err := response.Validate(); err != nil {
+					return err
+				}
+				return nil
+			}(); err != nil {
+				return res, errors.Wrap(err, "validate")
+			}
+			return &response, nil
+		default:
+			return res, validate.InvalidContentType(ct)
+		}
+	}
+	// Convenient error response.
+	defRes, err := func() (res *ErrorStatusCode, err error) {
+		ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
+		if err != nil {
+			return res, errors.Wrap(err, "parse media type")
+		}
+		switch {
+		case ct == "application/json":
+			buf, err := io.ReadAll(resp.Body)
+			if err != nil {
+				return res, err
+			}
+			d := jx.DecodeBytes(buf)
+
+			var response Error
+			if err := func() error {
+				if err := response.Decode(d); err != nil {
+					return err
+				}
+				if err := d.Skip(); err != io.EOF {
+					return errors.New("unexpected trailing data")
+				}
+				return nil
+			}(); err != nil {
+				err = &ogenerrors.DecodeBodyError{
+					ContentType: ct,
+					Body:        buf,
+					Err:         err,
+				}
+				return res, err
+			}
+			return &ErrorStatusCode{
+				StatusCode: resp.StatusCode,
+				Response:   response,
+			}, nil
+		default:
+			return res, validate.InvalidContentType(ct)
+		}
+	}()
+	if err != nil {
+		return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode)
+	}
+	return res, errors.Wrap(defRes, "error")
+}
+
 func decodeGetMapfixResponse(resp *http.Response) (res *Mapfix, _ error) {
 	switch resp.StatusCode {
 	case 200:
@@ -1852,6 +1944,123 @@ func decodeListMapfixesResponse(resp *http.Response) (res []Mapfix, _ error) {
 	return res, errors.Wrap(defRes, "error")
 }
 
+func decodeListMapsResponse(resp *http.Response) (res []Map, _ error) {
+	switch resp.StatusCode {
+	case 200:
+		// Code 200.
+		ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
+		if err != nil {
+			return res, errors.Wrap(err, "parse media type")
+		}
+		switch {
+		case ct == "application/json":
+			buf, err := io.ReadAll(resp.Body)
+			if err != nil {
+				return res, err
+			}
+			d := jx.DecodeBytes(buf)
+
+			var response []Map
+			if err := func() error {
+				response = make([]Map, 0)
+				if err := d.Arr(func(d *jx.Decoder) error {
+					var elem Map
+					if err := elem.Decode(d); err != nil {
+						return err
+					}
+					response = append(response, elem)
+					return nil
+				}); err != nil {
+					return err
+				}
+				if err := d.Skip(); err != io.EOF {
+					return errors.New("unexpected trailing data")
+				}
+				return nil
+			}(); err != nil {
+				err = &ogenerrors.DecodeBodyError{
+					ContentType: ct,
+					Body:        buf,
+					Err:         err,
+				}
+				return res, err
+			}
+			// Validate response.
+			if err := func() error {
+				if response == nil {
+					return errors.New("nil is invalid value")
+				}
+				var failures []validate.FieldError
+				for i, elem := range response {
+					if err := func() error {
+						if err := elem.Validate(); err != nil {
+							return err
+						}
+						return nil
+					}(); err != nil {
+						failures = append(failures, validate.FieldError{
+							Name:  fmt.Sprintf("[%d]", i),
+							Error: err,
+						})
+					}
+				}
+				if len(failures) > 0 {
+					return &validate.Error{Fields: failures}
+				}
+				return nil
+			}(); err != nil {
+				return res, errors.Wrap(err, "validate")
+			}
+			return response, nil
+		default:
+			return res, validate.InvalidContentType(ct)
+		}
+	}
+	// Convenient error response.
+	defRes, err := func() (res *ErrorStatusCode, err error) {
+		ct, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
+		if err != nil {
+			return res, errors.Wrap(err, "parse media type")
+		}
+		switch {
+		case ct == "application/json":
+			buf, err := io.ReadAll(resp.Body)
+			if err != nil {
+				return res, err
+			}
+			d := jx.DecodeBytes(buf)
+
+			var response Error
+			if err := func() error {
+				if err := response.Decode(d); err != nil {
+					return err
+				}
+				if err := d.Skip(); err != io.EOF {
+					return errors.New("unexpected trailing data")
+				}
+				return nil
+			}(); err != nil {
+				err = &ogenerrors.DecodeBodyError{
+					ContentType: ct,
+					Body:        buf,
+					Err:         err,
+				}
+				return res, err
+			}
+			return &ErrorStatusCode{
+				StatusCode: resp.StatusCode,
+				Response:   response,
+			}, nil
+		default:
+			return res, validate.InvalidContentType(ct)
+		}
+	}()
+	if err != nil {
+		return res, errors.Wrapf(err, "default (code %d)", resp.StatusCode)
+	}
+	return res, errors.Wrap(defRes, "error")
+}
+
 func decodeListScriptPolicyResponse(resp *http.Response) (res []ScriptPolicy, _ error) {
 	switch resp.StatusCode {
 	case 200:
diff --git a/pkg/api/oas_response_encoders_gen.go b/pkg/api/oas_response_encoders_gen.go
index 692f548..ba6c549 100644
--- a/pkg/api/oas_response_encoders_gen.go
+++ b/pkg/api/oas_response_encoders_gen.go
@@ -209,6 +209,20 @@ func encodeDeleteScriptPolicyResponse(response *DeleteScriptPolicyNoContent, w h
 	return nil
 }
 
+func encodeGetMapResponse(response *Map, w http.ResponseWriter, span trace.Span) error {
+	w.Header().Set("Content-Type", "application/json; charset=utf-8")
+	w.WriteHeader(200)
+	span.SetStatus(codes.Ok, http.StatusText(200))
+
+	e := new(jx.Encoder)
+	response.Encode(e)
+	if _, err := e.WriteTo(w); err != nil {
+		return errors.Wrap(err, "write")
+	}
+
+	return nil
+}
+
 func encodeGetMapfixResponse(response *Mapfix, w http.ResponseWriter, span trace.Span) error {
 	w.Header().Set("Content-Type", "application/json; charset=utf-8")
 	w.WriteHeader(200)
@@ -283,6 +297,24 @@ func encodeListMapfixesResponse(response []Mapfix, w http.ResponseWriter, span t
 	return nil
 }
 
+func encodeListMapsResponse(response []Map, w http.ResponseWriter, span trace.Span) error {
+	w.Header().Set("Content-Type", "application/json; charset=utf-8")
+	w.WriteHeader(200)
+	span.SetStatus(codes.Ok, http.StatusText(200))
+
+	e := new(jx.Encoder)
+	e.ArrStart()
+	for _, elem := range response {
+		elem.Encode(e)
+	}
+	e.ArrEnd()
+	if _, err := e.WriteTo(w); err != nil {
+		return errors.Wrap(err, "write")
+	}
+
+	return nil
+}
+
 func encodeListScriptPolicyResponse(response []ScriptPolicy, w http.ResponseWriter, span trace.Span) error {
 	w.Header().Set("Content-Type", "application/json; charset=utf-8")
 	w.WriteHeader(200)
diff --git a/pkg/api/oas_router_gen.go b/pkg/api/oas_router_gen.go
index fb0e008..6ebc1ef 100644
--- a/pkg/api/oas_router_gen.go
+++ b/pkg/api/oas_router_gen.go
@@ -61,50 +61,397 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 				break
 			}
 			switch elem[0] {
-			case 'm': // Prefix: "mapfixes"
+			case 'm': // Prefix: "map"
 
-				if l := len("mapfixes"); len(elem) >= l && elem[0:l] == "mapfixes" {
+				if l := len("map"); len(elem) >= l && elem[0:l] == "map" {
 					elem = elem[l:]
 				} else {
 					break
 				}
 
 				if len(elem) == 0 {
-					switch r.Method {
-					case "GET":
-						s.handleListMapfixesRequest([0]string{}, elemIsEscaped, w, r)
-					case "POST":
-						s.handleCreateMapfixRequest([0]string{}, elemIsEscaped, w, r)
-					default:
-						s.notAllowed(w, r, "GET,POST")
-					}
-
-					return
+					break
 				}
 				switch elem[0] {
-				case '/': // Prefix: "/"
+				case 'f': // Prefix: "fixes"
 
-					if l := len("/"); len(elem) >= l && elem[0:l] == "/" {
+					if l := len("fixes"); len(elem) >= l && elem[0:l] == "fixes" {
 						elem = elem[l:]
 					} else {
 						break
 					}
 
-					// Param: "MapfixID"
-					// Match until "/"
-					idx := strings.IndexByte(elem, '/')
-					if idx < 0 {
-						idx = len(elem)
+					if len(elem) == 0 {
+						switch r.Method {
+						case "GET":
+							s.handleListMapfixesRequest([0]string{}, elemIsEscaped, w, r)
+						case "POST":
+							s.handleCreateMapfixRequest([0]string{}, elemIsEscaped, w, r)
+						default:
+							s.notAllowed(w, r, "GET,POST")
+						}
+
+						return
+					}
+					switch elem[0] {
+					case '/': // Prefix: "/"
+
+						if l := len("/"); len(elem) >= l && elem[0:l] == "/" {
+							elem = elem[l:]
+						} else {
+							break
+						}
+
+						// Param: "MapfixID"
+						// Match until "/"
+						idx := strings.IndexByte(elem, '/')
+						if idx < 0 {
+							idx = len(elem)
+						}
+						args[0] = elem[:idx]
+						elem = elem[idx:]
+
+						if len(elem) == 0 {
+							switch r.Method {
+							case "GET":
+								s.handleGetMapfixRequest([1]string{
+									args[0],
+								}, elemIsEscaped, w, r)
+							default:
+								s.notAllowed(w, r, "GET")
+							}
+
+							return
+						}
+						switch elem[0] {
+						case '/': // Prefix: "/"
+
+							if l := len("/"); len(elem) >= l && elem[0:l] == "/" {
+								elem = elem[l:]
+							} else {
+								break
+							}
+
+							if len(elem) == 0 {
+								break
+							}
+							switch elem[0] {
+							case 'c': // Prefix: "completed"
+
+								if l := len("completed"); len(elem) >= l && elem[0:l] == "completed" {
+									elem = elem[l:]
+								} else {
+									break
+								}
+
+								if len(elem) == 0 {
+									// Leaf node.
+									switch r.Method {
+									case "POST":
+										s.handleSetMapfixCompletedRequest([1]string{
+											args[0],
+										}, elemIsEscaped, w, r)
+									default:
+										s.notAllowed(w, r, "POST")
+									}
+
+									return
+								}
+
+							case 'm': // Prefix: "model"
+
+								if l := len("model"); len(elem) >= l && elem[0:l] == "model" {
+									elem = elem[l:]
+								} else {
+									break
+								}
+
+								if len(elem) == 0 {
+									// Leaf node.
+									switch r.Method {
+									case "POST":
+										s.handleUpdateMapfixModelRequest([1]string{
+											args[0],
+										}, elemIsEscaped, w, r)
+									default:
+										s.notAllowed(w, r, "POST")
+									}
+
+									return
+								}
+
+							case 's': // Prefix: "status/"
+
+								if l := len("status/"); len(elem) >= l && elem[0:l] == "status/" {
+									elem = elem[l:]
+								} else {
+									break
+								}
+
+								if len(elem) == 0 {
+									break
+								}
+								switch elem[0] {
+								case 'r': // Prefix: "re"
+
+									if l := len("re"); len(elem) >= l && elem[0:l] == "re" {
+										elem = elem[l:]
+									} else {
+										break
+									}
+
+									if len(elem) == 0 {
+										break
+									}
+									switch elem[0] {
+									case 'j': // Prefix: "ject"
+
+										if l := len("ject"); len(elem) >= l && elem[0:l] == "ject" {
+											elem = elem[l:]
+										} else {
+											break
+										}
+
+										if len(elem) == 0 {
+											// Leaf node.
+											switch r.Method {
+											case "POST":
+												s.handleActionMapfixRejectRequest([1]string{
+													args[0],
+												}, elemIsEscaped, w, r)
+											default:
+												s.notAllowed(w, r, "POST")
+											}
+
+											return
+										}
+
+									case 'q': // Prefix: "quest-changes"
+
+										if l := len("quest-changes"); len(elem) >= l && elem[0:l] == "quest-changes" {
+											elem = elem[l:]
+										} else {
+											break
+										}
+
+										if len(elem) == 0 {
+											// Leaf node.
+											switch r.Method {
+											case "POST":
+												s.handleActionMapfixRequestChangesRequest([1]string{
+													args[0],
+												}, elemIsEscaped, w, r)
+											default:
+												s.notAllowed(w, r, "POST")
+											}
+
+											return
+										}
+
+									case 's': // Prefix: "set-"
+
+										if l := len("set-"); len(elem) >= l && elem[0:l] == "set-" {
+											elem = elem[l:]
+										} else {
+											break
+										}
+
+										if len(elem) == 0 {
+											break
+										}
+										switch elem[0] {
+										case 'u': // Prefix: "uploading"
+
+											if l := len("uploading"); len(elem) >= l && elem[0:l] == "uploading" {
+												elem = elem[l:]
+											} else {
+												break
+											}
+
+											if len(elem) == 0 {
+												// Leaf node.
+												switch r.Method {
+												case "POST":
+													s.handleActionMapfixValidatedRequest([1]string{
+														args[0],
+													}, elemIsEscaped, w, r)
+												default:
+													s.notAllowed(w, r, "POST")
+												}
+
+												return
+											}
+
+										case 'v': // Prefix: "validating"
+
+											if l := len("validating"); len(elem) >= l && elem[0:l] == "validating" {
+												elem = elem[l:]
+											} else {
+												break
+											}
+
+											if len(elem) == 0 {
+												// Leaf node.
+												switch r.Method {
+												case "POST":
+													s.handleActionMapfixAcceptedRequest([1]string{
+														args[0],
+													}, elemIsEscaped, w, r)
+												default:
+													s.notAllowed(w, r, "POST")
+												}
+
+												return
+											}
+
+										}
+
+									case 't': // Prefix: "try-validate"
+
+										if l := len("try-validate"); len(elem) >= l && elem[0:l] == "try-validate" {
+											elem = elem[l:]
+										} else {
+											break
+										}
+
+										if len(elem) == 0 {
+											// Leaf node.
+											switch r.Method {
+											case "POST":
+												s.handleActionMapfixRetryValidateRequest([1]string{
+													args[0],
+												}, elemIsEscaped, w, r)
+											default:
+												s.notAllowed(w, r, "POST")
+											}
+
+											return
+										}
+
+									case 'v': // Prefix: "voke"
+
+										if l := len("voke"); len(elem) >= l && elem[0:l] == "voke" {
+											elem = elem[l:]
+										} else {
+											break
+										}
+
+										if len(elem) == 0 {
+											// Leaf node.
+											switch r.Method {
+											case "POST":
+												s.handleActionMapfixRevokeRequest([1]string{
+													args[0],
+												}, elemIsEscaped, w, r)
+											default:
+												s.notAllowed(w, r, "POST")
+											}
+
+											return
+										}
+
+									}
+
+								case 's': // Prefix: "submit"
+
+									if l := len("submit"); len(elem) >= l && elem[0:l] == "submit" {
+										elem = elem[l:]
+									} else {
+										break
+									}
+
+									if len(elem) == 0 {
+										// Leaf node.
+										switch r.Method {
+										case "POST":
+											s.handleActionMapfixSubmitRequest([1]string{
+												args[0],
+											}, elemIsEscaped, w, r)
+										default:
+											s.notAllowed(w, r, "POST")
+										}
+
+										return
+									}
+
+								case 't': // Prefix: "trigger-"
+
+									if l := len("trigger-"); len(elem) >= l && elem[0:l] == "trigger-" {
+										elem = elem[l:]
+									} else {
+										break
+									}
+
+									if len(elem) == 0 {
+										break
+									}
+									switch elem[0] {
+									case 'u': // Prefix: "upload"
+
+										if l := len("upload"); len(elem) >= l && elem[0:l] == "upload" {
+											elem = elem[l:]
+										} else {
+											break
+										}
+
+										if len(elem) == 0 {
+											// Leaf node.
+											switch r.Method {
+											case "POST":
+												s.handleActionMapfixTriggerUploadRequest([1]string{
+													args[0],
+												}, elemIsEscaped, w, r)
+											default:
+												s.notAllowed(w, r, "POST")
+											}
+
+											return
+										}
+
+									case 'v': // Prefix: "validate"
+
+										if l := len("validate"); len(elem) >= l && elem[0:l] == "validate" {
+											elem = elem[l:]
+										} else {
+											break
+										}
+
+										if len(elem) == 0 {
+											// Leaf node.
+											switch r.Method {
+											case "POST":
+												s.handleActionMapfixTriggerValidateRequest([1]string{
+													args[0],
+												}, elemIsEscaped, w, r)
+											default:
+												s.notAllowed(w, r, "POST")
+											}
+
+											return
+										}
+
+									}
+
+								}
+
+							}
+
+						}
+
+					}
+
+				case 's': // Prefix: "s"
+
+					if l := len("s"); len(elem) >= l && elem[0:l] == "s" {
+						elem = elem[l:]
+					} else {
+						break
 					}
-					args[0] = elem[:idx]
-					elem = elem[idx:]
 
 					if len(elem) == 0 {
 						switch r.Method {
 						case "GET":
-							s.handleGetMapfixRequest([1]string{
-								args[0],
-							}, elemIsEscaped, w, r)
+							s.handleListMapsRequest([0]string{}, elemIsEscaped, w, r)
 						default:
 							s.notAllowed(w, r, "GET")
 						}
@@ -120,308 +467,27 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 							break
 						}
 
-						if len(elem) == 0 {
+						// Param: "MapID"
+						// Leaf parameter, slashes are prohibited
+						idx := strings.IndexByte(elem, '/')
+						if idx >= 0 {
 							break
 						}
-						switch elem[0] {
-						case 'c': // Prefix: "completed"
-
-							if l := len("completed"); len(elem) >= l && elem[0:l] == "completed" {
-								elem = elem[l:]
-							} else {
-								break
-							}
-
-							if len(elem) == 0 {
-								// Leaf node.
-								switch r.Method {
-								case "POST":
-									s.handleSetMapfixCompletedRequest([1]string{
-										args[0],
-									}, elemIsEscaped, w, r)
-								default:
-									s.notAllowed(w, r, "POST")
-								}
-
-								return
-							}
-
-						case 'm': // Prefix: "model"
-
-							if l := len("model"); len(elem) >= l && elem[0:l] == "model" {
-								elem = elem[l:]
-							} else {
-								break
-							}
-
-							if len(elem) == 0 {
-								// Leaf node.
-								switch r.Method {
-								case "POST":
-									s.handleUpdateMapfixModelRequest([1]string{
-										args[0],
-									}, elemIsEscaped, w, r)
-								default:
-									s.notAllowed(w, r, "POST")
-								}
-
-								return
-							}
-
-						case 's': // Prefix: "status/"
-
-							if l := len("status/"); len(elem) >= l && elem[0:l] == "status/" {
-								elem = elem[l:]
-							} else {
-								break
-							}
-
-							if len(elem) == 0 {
-								break
-							}
-							switch elem[0] {
-							case 'r': // Prefix: "re"
-
-								if l := len("re"); len(elem) >= l && elem[0:l] == "re" {
-									elem = elem[l:]
-								} else {
-									break
-								}
-
-								if len(elem) == 0 {
-									break
-								}
-								switch elem[0] {
-								case 'j': // Prefix: "ject"
-
-									if l := len("ject"); len(elem) >= l && elem[0:l] == "ject" {
-										elem = elem[l:]
-									} else {
-										break
-									}
-
-									if len(elem) == 0 {
-										// Leaf node.
-										switch r.Method {
-										case "POST":
-											s.handleActionMapfixRejectRequest([1]string{
-												args[0],
-											}, elemIsEscaped, w, r)
-										default:
-											s.notAllowed(w, r, "POST")
-										}
-
-										return
-									}
-
-								case 'q': // Prefix: "quest-changes"
-
-									if l := len("quest-changes"); len(elem) >= l && elem[0:l] == "quest-changes" {
-										elem = elem[l:]
-									} else {
-										break
-									}
-
-									if len(elem) == 0 {
-										// Leaf node.
-										switch r.Method {
-										case "POST":
-											s.handleActionMapfixRequestChangesRequest([1]string{
-												args[0],
-											}, elemIsEscaped, w, r)
-										default:
-											s.notAllowed(w, r, "POST")
-										}
-
-										return
-									}
-
-								case 's': // Prefix: "set-"
-
-									if l := len("set-"); len(elem) >= l && elem[0:l] == "set-" {
-										elem = elem[l:]
-									} else {
-										break
-									}
-
-									if len(elem) == 0 {
-										break
-									}
-									switch elem[0] {
-									case 'u': // Prefix: "uploading"
-
-										if l := len("uploading"); len(elem) >= l && elem[0:l] == "uploading" {
-											elem = elem[l:]
-										} else {
-											break
-										}
-
-										if len(elem) == 0 {
-											// Leaf node.
-											switch r.Method {
-											case "POST":
-												s.handleActionMapfixValidatedRequest([1]string{
-													args[0],
-												}, elemIsEscaped, w, r)
-											default:
-												s.notAllowed(w, r, "POST")
-											}
-
-											return
-										}
-
-									case 'v': // Prefix: "validating"
-
-										if l := len("validating"); len(elem) >= l && elem[0:l] == "validating" {
-											elem = elem[l:]
-										} else {
-											break
-										}
-
-										if len(elem) == 0 {
-											// Leaf node.
-											switch r.Method {
-											case "POST":
-												s.handleActionMapfixAcceptedRequest([1]string{
-													args[0],
-												}, elemIsEscaped, w, r)
-											default:
-												s.notAllowed(w, r, "POST")
-											}
-
-											return
-										}
-
-									}
-
-								case 't': // Prefix: "try-validate"
-
-									if l := len("try-validate"); len(elem) >= l && elem[0:l] == "try-validate" {
-										elem = elem[l:]
-									} else {
-										break
-									}
-
-									if len(elem) == 0 {
-										// Leaf node.
-										switch r.Method {
-										case "POST":
-											s.handleActionMapfixRetryValidateRequest([1]string{
-												args[0],
-											}, elemIsEscaped, w, r)
-										default:
-											s.notAllowed(w, r, "POST")
-										}
-
-										return
-									}
-
-								case 'v': // Prefix: "voke"
-
-									if l := len("voke"); len(elem) >= l && elem[0:l] == "voke" {
-										elem = elem[l:]
-									} else {
-										break
-									}
-
-									if len(elem) == 0 {
-										// Leaf node.
-										switch r.Method {
-										case "POST":
-											s.handleActionMapfixRevokeRequest([1]string{
-												args[0],
-											}, elemIsEscaped, w, r)
-										default:
-											s.notAllowed(w, r, "POST")
-										}
-
-										return
-									}
-
-								}
-
-							case 's': // Prefix: "submit"
-
-								if l := len("submit"); len(elem) >= l && elem[0:l] == "submit" {
-									elem = elem[l:]
-								} else {
-									break
-								}
-
-								if len(elem) == 0 {
-									// Leaf node.
-									switch r.Method {
-									case "POST":
-										s.handleActionMapfixSubmitRequest([1]string{
-											args[0],
-										}, elemIsEscaped, w, r)
-									default:
-										s.notAllowed(w, r, "POST")
-									}
-
-									return
-								}
-
-							case 't': // Prefix: "trigger-"
-
-								if l := len("trigger-"); len(elem) >= l && elem[0:l] == "trigger-" {
-									elem = elem[l:]
-								} else {
-									break
-								}
-
-								if len(elem) == 0 {
-									break
-								}
-								switch elem[0] {
-								case 'u': // Prefix: "upload"
-
-									if l := len("upload"); len(elem) >= l && elem[0:l] == "upload" {
-										elem = elem[l:]
-									} else {
-										break
-									}
-
-									if len(elem) == 0 {
-										// Leaf node.
-										switch r.Method {
-										case "POST":
-											s.handleActionMapfixTriggerUploadRequest([1]string{
-												args[0],
-											}, elemIsEscaped, w, r)
-										default:
-											s.notAllowed(w, r, "POST")
-										}
-
-										return
-									}
-
-								case 'v': // Prefix: "validate"
-
-									if l := len("validate"); len(elem) >= l && elem[0:l] == "validate" {
-										elem = elem[l:]
-									} else {
-										break
-									}
-
-									if len(elem) == 0 {
-										// Leaf node.
-										switch r.Method {
-										case "POST":
-											s.handleActionMapfixTriggerValidateRequest([1]string{
-												args[0],
-											}, elemIsEscaped, w, r)
-										default:
-											s.notAllowed(w, r, "POST")
-										}
-
-										return
-									}
-
-								}
+						args[0] = elem
+						elem = ""
 
+						if len(elem) == 0 {
+							// Leaf node.
+							switch r.Method {
+							case "GET":
+								s.handleGetMapRequest([1]string{
+									args[0],
+								}, elemIsEscaped, w, r)
+							default:
+								s.notAllowed(w, r, "GET")
 							}
 
+							return
 						}
 
 					}
@@ -1135,63 +1201,43 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
 				break
 			}
 			switch elem[0] {
-			case 'm': // Prefix: "mapfixes"
+			case 'm': // Prefix: "map"
 
-				if l := len("mapfixes"); len(elem) >= l && elem[0:l] == "mapfixes" {
+				if l := len("map"); len(elem) >= l && elem[0:l] == "map" {
 					elem = elem[l:]
 				} else {
 					break
 				}
 
 				if len(elem) == 0 {
-					switch method {
-					case "GET":
-						r.name = ListMapfixesOperation
-						r.summary = "Get list of mapfixes"
-						r.operationID = "listMapfixes"
-						r.pathPattern = "/mapfixes"
-						r.args = args
-						r.count = 0
-						return r, true
-					case "POST":
-						r.name = CreateMapfixOperation
-						r.summary = "Create new mapfix"
-						r.operationID = "createMapfix"
-						r.pathPattern = "/mapfixes"
-						r.args = args
-						r.count = 0
-						return r, true
-					default:
-						return
-					}
+					break
 				}
 				switch elem[0] {
-				case '/': // Prefix: "/"
+				case 'f': // Prefix: "fixes"
 
-					if l := len("/"); len(elem) >= l && elem[0:l] == "/" {
+					if l := len("fixes"); len(elem) >= l && elem[0:l] == "fixes" {
 						elem = elem[l:]
 					} else {
 						break
 					}
 
-					// Param: "MapfixID"
-					// Match until "/"
-					idx := strings.IndexByte(elem, '/')
-					if idx < 0 {
-						idx = len(elem)
-					}
-					args[0] = elem[:idx]
-					elem = elem[idx:]
-
 					if len(elem) == 0 {
 						switch method {
 						case "GET":
-							r.name = GetMapfixOperation
-							r.summary = "Retrieve map with ID"
-							r.operationID = "getMapfix"
-							r.pathPattern = "/mapfixes/{MapfixID}"
+							r.name = ListMapfixesOperation
+							r.summary = "Get list of mapfixes"
+							r.operationID = "listMapfixes"
+							r.pathPattern = "/mapfixes"
 							r.args = args
-							r.count = 1
+							r.count = 0
+							return r, true
+						case "POST":
+							r.name = CreateMapfixOperation
+							r.summary = "Create new mapfix"
+							r.operationID = "createMapfix"
+							r.pathPattern = "/mapfixes"
+							r.args = args
+							r.count = 0
 							return r, true
 						default:
 							return
@@ -1206,61 +1252,33 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
 							break
 						}
 
+						// Param: "MapfixID"
+						// Match until "/"
+						idx := strings.IndexByte(elem, '/')
+						if idx < 0 {
+							idx = len(elem)
+						}
+						args[0] = elem[:idx]
+						elem = elem[idx:]
+
 						if len(elem) == 0 {
-							break
+							switch method {
+							case "GET":
+								r.name = GetMapfixOperation
+								r.summary = "Retrieve map with ID"
+								r.operationID = "getMapfix"
+								r.pathPattern = "/mapfixes/{MapfixID}"
+								r.args = args
+								r.count = 1
+								return r, true
+							default:
+								return
+							}
 						}
 						switch elem[0] {
-						case 'c': // Prefix: "completed"
+						case '/': // Prefix: "/"
 
-							if l := len("completed"); len(elem) >= l && elem[0:l] == "completed" {
-								elem = elem[l:]
-							} else {
-								break
-							}
-
-							if len(elem) == 0 {
-								// Leaf node.
-								switch method {
-								case "POST":
-									r.name = SetMapfixCompletedOperation
-									r.summary = "Called by maptest when a player completes the map"
-									r.operationID = "setMapfixCompleted"
-									r.pathPattern = "/mapfixes/{MapfixID}/completed"
-									r.args = args
-									r.count = 1
-									return r, true
-								default:
-									return
-								}
-							}
-
-						case 'm': // Prefix: "model"
-
-							if l := len("model"); len(elem) >= l && elem[0:l] == "model" {
-								elem = elem[l:]
-							} else {
-								break
-							}
-
-							if len(elem) == 0 {
-								// Leaf node.
-								switch method {
-								case "POST":
-									r.name = UpdateMapfixModelOperation
-									r.summary = "Update model following role restrictions"
-									r.operationID = "updateMapfixModel"
-									r.pathPattern = "/mapfixes/{MapfixID}/model"
-									r.args = args
-									r.count = 1
-									return r, true
-								default:
-									return
-								}
-							}
-
-						case 's': // Prefix: "status/"
-
-							if l := len("status/"); len(elem) >= l && elem[0:l] == "status/" {
+							if l := len("/"); len(elem) >= l && elem[0:l] == "/" {
 								elem = elem[l:]
 							} else {
 								break
@@ -1270,181 +1288,9 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
 								break
 							}
 							switch elem[0] {
-							case 'r': // Prefix: "re"
+							case 'c': // Prefix: "completed"
 
-								if l := len("re"); len(elem) >= l && elem[0:l] == "re" {
-									elem = elem[l:]
-								} else {
-									break
-								}
-
-								if len(elem) == 0 {
-									break
-								}
-								switch elem[0] {
-								case 'j': // Prefix: "ject"
-
-									if l := len("ject"); len(elem) >= l && elem[0:l] == "ject" {
-										elem = elem[l:]
-									} else {
-										break
-									}
-
-									if len(elem) == 0 {
-										// Leaf node.
-										switch method {
-										case "POST":
-											r.name = ActionMapfixRejectOperation
-											r.summary = "Role Reviewer changes status from Submitted -> Rejected"
-											r.operationID = "actionMapfixReject"
-											r.pathPattern = "/mapfixes/{MapfixID}/status/reject"
-											r.args = args
-											r.count = 1
-											return r, true
-										default:
-											return
-										}
-									}
-
-								case 'q': // Prefix: "quest-changes"
-
-									if l := len("quest-changes"); len(elem) >= l && elem[0:l] == "quest-changes" {
-										elem = elem[l:]
-									} else {
-										break
-									}
-
-									if len(elem) == 0 {
-										// Leaf node.
-										switch method {
-										case "POST":
-											r.name = ActionMapfixRequestChangesOperation
-											r.summary = "Role Reviewer changes status from Validated|Accepted|Submitted -> ChangesRequested"
-											r.operationID = "actionMapfixRequestChanges"
-											r.pathPattern = "/mapfixes/{MapfixID}/status/request-changes"
-											r.args = args
-											r.count = 1
-											return r, true
-										default:
-											return
-										}
-									}
-
-								case 's': // Prefix: "set-"
-
-									if l := len("set-"); len(elem) >= l && elem[0:l] == "set-" {
-										elem = elem[l:]
-									} else {
-										break
-									}
-
-									if len(elem) == 0 {
-										break
-									}
-									switch elem[0] {
-									case 'u': // Prefix: "uploading"
-
-										if l := len("uploading"); len(elem) >= l && elem[0:l] == "uploading" {
-											elem = elem[l:]
-										} else {
-											break
-										}
-
-										if len(elem) == 0 {
-											// Leaf node.
-											switch method {
-											case "POST":
-												r.name = ActionMapfixValidatedOperation
-												r.summary = "Role Admin manually resets uploading softlock and changes status from Uploading -> Validated"
-												r.operationID = "actionMapfixValidated"
-												r.pathPattern = "/mapfixes/{MapfixID}/status/reset-uploading"
-												r.args = args
-												r.count = 1
-												return r, true
-											default:
-												return
-											}
-										}
-
-									case 'v': // Prefix: "validating"
-
-										if l := len("validating"); len(elem) >= l && elem[0:l] == "validating" {
-											elem = elem[l:]
-										} else {
-											break
-										}
-
-										if len(elem) == 0 {
-											// Leaf node.
-											switch method {
-											case "POST":
-												r.name = ActionMapfixAcceptedOperation
-												r.summary = "Role Reviewer manually resets validating softlock and changes status from Validating -> Accepted"
-												r.operationID = "actionMapfixAccepted"
-												r.pathPattern = "/mapfixes/{MapfixID}/status/reset-validating"
-												r.args = args
-												r.count = 1
-												return r, true
-											default:
-												return
-											}
-										}
-
-									}
-
-								case 't': // Prefix: "try-validate"
-
-									if l := len("try-validate"); len(elem) >= l && elem[0:l] == "try-validate" {
-										elem = elem[l:]
-									} else {
-										break
-									}
-
-									if len(elem) == 0 {
-										// Leaf node.
-										switch method {
-										case "POST":
-											r.name = ActionMapfixRetryValidateOperation
-											r.summary = "Role Reviewer re-runs validation and changes status from Accepted -> Validating"
-											r.operationID = "actionMapfixRetryValidate"
-											r.pathPattern = "/mapfixes/{MapfixID}/status/retry-validate"
-											r.args = args
-											r.count = 1
-											return r, true
-										default:
-											return
-										}
-									}
-
-								case 'v': // Prefix: "voke"
-
-									if l := len("voke"); len(elem) >= l && elem[0:l] == "voke" {
-										elem = elem[l:]
-									} else {
-										break
-									}
-
-									if len(elem) == 0 {
-										// Leaf node.
-										switch method {
-										case "POST":
-											r.name = ActionMapfixRevokeOperation
-											r.summary = "Role Submitter changes status from Submitted|ChangesRequested -> UnderConstruction"
-											r.operationID = "actionMapfixRevoke"
-											r.pathPattern = "/mapfixes/{MapfixID}/status/revoke"
-											r.args = args
-											r.count = 1
-											return r, true
-										default:
-											return
-										}
-									}
-
-								}
-
-							case 's': // Prefix: "submit"
-
-								if l := len("submit"); len(elem) >= l && elem[0:l] == "submit" {
+								if l := len("completed"); len(elem) >= l && elem[0:l] == "completed" {
 									elem = elem[l:]
 								} else {
 									break
@@ -1454,10 +1300,10 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
 									// Leaf node.
 									switch method {
 									case "POST":
-										r.name = ActionMapfixSubmitOperation
-										r.summary = "Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitted"
-										r.operationID = "actionMapfixSubmit"
-										r.pathPattern = "/mapfixes/{MapfixID}/status/submit"
+										r.name = SetMapfixCompletedOperation
+										r.summary = "Called by maptest when a player completes the map"
+										r.operationID = "setMapfixCompleted"
+										r.pathPattern = "/mapfixes/{MapfixID}/completed"
 										r.args = args
 										r.count = 1
 										return r, true
@@ -1466,9 +1312,33 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
 									}
 								}
 
-							case 't': // Prefix: "trigger-"
+							case 'm': // Prefix: "model"
 
-								if l := len("trigger-"); len(elem) >= l && elem[0:l] == "trigger-" {
+								if l := len("model"); len(elem) >= l && elem[0:l] == "model" {
+									elem = elem[l:]
+								} else {
+									break
+								}
+
+								if len(elem) == 0 {
+									// Leaf node.
+									switch method {
+									case "POST":
+										r.name = UpdateMapfixModelOperation
+										r.summary = "Update model following role restrictions"
+										r.operationID = "updateMapfixModel"
+										r.pathPattern = "/mapfixes/{MapfixID}/model"
+										r.args = args
+										r.count = 1
+										return r, true
+									default:
+										return
+									}
+								}
+
+							case 's': // Prefix: "status/"
+
+								if l := len("status/"); len(elem) >= l && elem[0:l] == "status/" {
 									elem = elem[l:]
 								} else {
 									break
@@ -1478,9 +1348,181 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
 									break
 								}
 								switch elem[0] {
-								case 'u': // Prefix: "upload"
+								case 'r': // Prefix: "re"
 
-									if l := len("upload"); len(elem) >= l && elem[0:l] == "upload" {
+									if l := len("re"); len(elem) >= l && elem[0:l] == "re" {
+										elem = elem[l:]
+									} else {
+										break
+									}
+
+									if len(elem) == 0 {
+										break
+									}
+									switch elem[0] {
+									case 'j': // Prefix: "ject"
+
+										if l := len("ject"); len(elem) >= l && elem[0:l] == "ject" {
+											elem = elem[l:]
+										} else {
+											break
+										}
+
+										if len(elem) == 0 {
+											// Leaf node.
+											switch method {
+											case "POST":
+												r.name = ActionMapfixRejectOperation
+												r.summary = "Role Reviewer changes status from Submitted -> Rejected"
+												r.operationID = "actionMapfixReject"
+												r.pathPattern = "/mapfixes/{MapfixID}/status/reject"
+												r.args = args
+												r.count = 1
+												return r, true
+											default:
+												return
+											}
+										}
+
+									case 'q': // Prefix: "quest-changes"
+
+										if l := len("quest-changes"); len(elem) >= l && elem[0:l] == "quest-changes" {
+											elem = elem[l:]
+										} else {
+											break
+										}
+
+										if len(elem) == 0 {
+											// Leaf node.
+											switch method {
+											case "POST":
+												r.name = ActionMapfixRequestChangesOperation
+												r.summary = "Role Reviewer changes status from Validated|Accepted|Submitted -> ChangesRequested"
+												r.operationID = "actionMapfixRequestChanges"
+												r.pathPattern = "/mapfixes/{MapfixID}/status/request-changes"
+												r.args = args
+												r.count = 1
+												return r, true
+											default:
+												return
+											}
+										}
+
+									case 's': // Prefix: "set-"
+
+										if l := len("set-"); len(elem) >= l && elem[0:l] == "set-" {
+											elem = elem[l:]
+										} else {
+											break
+										}
+
+										if len(elem) == 0 {
+											break
+										}
+										switch elem[0] {
+										case 'u': // Prefix: "uploading"
+
+											if l := len("uploading"); len(elem) >= l && elem[0:l] == "uploading" {
+												elem = elem[l:]
+											} else {
+												break
+											}
+
+											if len(elem) == 0 {
+												// Leaf node.
+												switch method {
+												case "POST":
+													r.name = ActionMapfixValidatedOperation
+													r.summary = "Role Admin manually resets uploading softlock and changes status from Uploading -> Validated"
+													r.operationID = "actionMapfixValidated"
+													r.pathPattern = "/mapfixes/{MapfixID}/status/reset-uploading"
+													r.args = args
+													r.count = 1
+													return r, true
+												default:
+													return
+												}
+											}
+
+										case 'v': // Prefix: "validating"
+
+											if l := len("validating"); len(elem) >= l && elem[0:l] == "validating" {
+												elem = elem[l:]
+											} else {
+												break
+											}
+
+											if len(elem) == 0 {
+												// Leaf node.
+												switch method {
+												case "POST":
+													r.name = ActionMapfixAcceptedOperation
+													r.summary = "Role Reviewer manually resets validating softlock and changes status from Validating -> Accepted"
+													r.operationID = "actionMapfixAccepted"
+													r.pathPattern = "/mapfixes/{MapfixID}/status/reset-validating"
+													r.args = args
+													r.count = 1
+													return r, true
+												default:
+													return
+												}
+											}
+
+										}
+
+									case 't': // Prefix: "try-validate"
+
+										if l := len("try-validate"); len(elem) >= l && elem[0:l] == "try-validate" {
+											elem = elem[l:]
+										} else {
+											break
+										}
+
+										if len(elem) == 0 {
+											// Leaf node.
+											switch method {
+											case "POST":
+												r.name = ActionMapfixRetryValidateOperation
+												r.summary = "Role Reviewer re-runs validation and changes status from Accepted -> Validating"
+												r.operationID = "actionMapfixRetryValidate"
+												r.pathPattern = "/mapfixes/{MapfixID}/status/retry-validate"
+												r.args = args
+												r.count = 1
+												return r, true
+											default:
+												return
+											}
+										}
+
+									case 'v': // Prefix: "voke"
+
+										if l := len("voke"); len(elem) >= l && elem[0:l] == "voke" {
+											elem = elem[l:]
+										} else {
+											break
+										}
+
+										if len(elem) == 0 {
+											// Leaf node.
+											switch method {
+											case "POST":
+												r.name = ActionMapfixRevokeOperation
+												r.summary = "Role Submitter changes status from Submitted|ChangesRequested -> UnderConstruction"
+												r.operationID = "actionMapfixRevoke"
+												r.pathPattern = "/mapfixes/{MapfixID}/status/revoke"
+												r.args = args
+												r.count = 1
+												return r, true
+											default:
+												return
+											}
+										}
+
+									}
+
+								case 's': // Prefix: "submit"
+
+									if l := len("submit"); len(elem) >= l && elem[0:l] == "submit" {
 										elem = elem[l:]
 									} else {
 										break
@@ -1490,10 +1532,10 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
 										// Leaf node.
 										switch method {
 										case "POST":
-											r.name = ActionMapfixTriggerUploadOperation
-											r.summary = "Role Admin changes status from Validated -> Uploading"
-											r.operationID = "actionMapfixTriggerUpload"
-											r.pathPattern = "/mapfixes/{MapfixID}/status/trigger-upload"
+											r.name = ActionMapfixSubmitOperation
+											r.summary = "Role Submitter changes status from UnderConstruction|ChangesRequested -> Submitted"
+											r.operationID = "actionMapfixSubmit"
+											r.pathPattern = "/mapfixes/{MapfixID}/status/submit"
 											r.args = args
 											r.count = 1
 											return r, true
@@ -1502,28 +1544,66 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
 										}
 									}
 
-								case 'v': // Prefix: "validate"
+								case 't': // Prefix: "trigger-"
 
-									if l := len("validate"); len(elem) >= l && elem[0:l] == "validate" {
+									if l := len("trigger-"); len(elem) >= l && elem[0:l] == "trigger-" {
 										elem = elem[l:]
 									} else {
 										break
 									}
 
 									if len(elem) == 0 {
-										// Leaf node.
-										switch method {
-										case "POST":
-											r.name = ActionMapfixTriggerValidateOperation
-											r.summary = "Role Reviewer triggers validation and changes status from Submitted -> Validating"
-											r.operationID = "actionMapfixTriggerValidate"
-											r.pathPattern = "/mapfixes/{MapfixID}/status/trigger-validate"
-											r.args = args
-											r.count = 1
-											return r, true
-										default:
-											return
+										break
+									}
+									switch elem[0] {
+									case 'u': // Prefix: "upload"
+
+										if l := len("upload"); len(elem) >= l && elem[0:l] == "upload" {
+											elem = elem[l:]
+										} else {
+											break
 										}
+
+										if len(elem) == 0 {
+											// Leaf node.
+											switch method {
+											case "POST":
+												r.name = ActionMapfixTriggerUploadOperation
+												r.summary = "Role Admin changes status from Validated -> Uploading"
+												r.operationID = "actionMapfixTriggerUpload"
+												r.pathPattern = "/mapfixes/{MapfixID}/status/trigger-upload"
+												r.args = args
+												r.count = 1
+												return r, true
+											default:
+												return
+											}
+										}
+
+									case 'v': // Prefix: "validate"
+
+										if l := len("validate"); len(elem) >= l && elem[0:l] == "validate" {
+											elem = elem[l:]
+										} else {
+											break
+										}
+
+										if len(elem) == 0 {
+											// Leaf node.
+											switch method {
+											case "POST":
+												r.name = ActionMapfixTriggerValidateOperation
+												r.summary = "Role Reviewer triggers validation and changes status from Submitted -> Validating"
+												r.operationID = "actionMapfixTriggerValidate"
+												r.pathPattern = "/mapfixes/{MapfixID}/status/trigger-validate"
+												r.args = args
+												r.count = 1
+												return r, true
+											default:
+												return
+											}
+										}
+
 									}
 
 								}
@@ -1534,6 +1614,64 @@ func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
 
 					}
 
+				case 's': // Prefix: "s"
+
+					if l := len("s"); len(elem) >= l && elem[0:l] == "s" {
+						elem = elem[l:]
+					} else {
+						break
+					}
+
+					if len(elem) == 0 {
+						switch method {
+						case "GET":
+							r.name = ListMapsOperation
+							r.summary = "Get list of maps"
+							r.operationID = "listMaps"
+							r.pathPattern = "/maps"
+							r.args = args
+							r.count = 0
+							return r, true
+						default:
+							return
+						}
+					}
+					switch elem[0] {
+					case '/': // Prefix: "/"
+
+						if l := len("/"); len(elem) >= l && elem[0:l] == "/" {
+							elem = elem[l:]
+						} else {
+							break
+						}
+
+						// Param: "MapID"
+						// Leaf parameter, slashes are prohibited
+						idx := strings.IndexByte(elem, '/')
+						if idx >= 0 {
+							break
+						}
+						args[0] = elem
+						elem = ""
+
+						if len(elem) == 0 {
+							// Leaf node.
+							switch method {
+							case "GET":
+								r.name = GetMapOperation
+								r.summary = "Retrieve map with ID"
+								r.operationID = "getMap"
+								r.pathPattern = "/maps/{MapID}"
+								r.args = args
+								r.count = 1
+								return r, true
+							default:
+								return
+							}
+						}
+
+					}
+
 				}
 
 			case 'r': // Prefix: "release-submissions"
diff --git a/pkg/api/oas_schemas_gen.go b/pkg/api/oas_schemas_gen.go
index 9fd7e10..4c368c2 100644
--- a/pkg/api/oas_schemas_gen.go
+++ b/pkg/api/oas_schemas_gen.go
@@ -153,6 +153,65 @@ func (s *ID) SetID(val int64) {
 	s.ID = val
 }
 
+// Ref: #/components/schemas/Map
+type Map struct {
+	ID          int64  `json:"ID"`
+	DisplayName string `json:"DisplayName"`
+	Creator     string `json:"Creator"`
+	GameID      int32  `json:"GameID"`
+	Date        int64  `json:"Date"`
+}
+
+// GetID returns the value of ID.
+func (s *Map) GetID() int64 {
+	return s.ID
+}
+
+// GetDisplayName returns the value of DisplayName.
+func (s *Map) GetDisplayName() string {
+	return s.DisplayName
+}
+
+// GetCreator returns the value of Creator.
+func (s *Map) GetCreator() string {
+	return s.Creator
+}
+
+// GetGameID returns the value of GameID.
+func (s *Map) GetGameID() int32 {
+	return s.GameID
+}
+
+// GetDate returns the value of Date.
+func (s *Map) GetDate() int64 {
+	return s.Date
+}
+
+// SetID sets the value of ID.
+func (s *Map) SetID(val int64) {
+	s.ID = val
+}
+
+// SetDisplayName sets the value of DisplayName.
+func (s *Map) SetDisplayName(val string) {
+	s.DisplayName = val
+}
+
+// SetCreator sets the value of Creator.
+func (s *Map) SetCreator(val string) {
+	s.Creator = val
+}
+
+// SetGameID sets the value of GameID.
+func (s *Map) SetGameID(val int32) {
+	s.GameID = val
+}
+
+// SetDate sets the value of Date.
+func (s *Map) SetDate(val int64) {
+	s.Date = val
+}
+
 // Ref: #/components/schemas/Mapfix
 type Mapfix struct {
 	ID            int64  `json:"ID"`
diff --git a/pkg/api/oas_server_gen.go b/pkg/api/oas_server_gen.go
index 8b0b85c..9f294eb 100644
--- a/pkg/api/oas_server_gen.go
+++ b/pkg/api/oas_server_gen.go
@@ -152,6 +152,12 @@ type Handler interface {
 	//
 	// DELETE /script-policy/{ScriptPolicyID}
 	DeleteScriptPolicy(ctx context.Context, params DeleteScriptPolicyParams) error
+	// GetMap implements getMap operation.
+	//
+	// Retrieve map with ID.
+	//
+	// GET /maps/{MapID}
+	GetMap(ctx context.Context, params GetMapParams) (*Map, error)
 	// GetMapfix implements getMapfix operation.
 	//
 	// Retrieve map with ID.
@@ -182,6 +188,12 @@ type Handler interface {
 	//
 	// GET /mapfixes
 	ListMapfixes(ctx context.Context, params ListMapfixesParams) ([]Mapfix, error)
+	// ListMaps implements listMaps operation.
+	//
+	// Get list of maps.
+	//
+	// GET /maps
+	ListMaps(ctx context.Context, params ListMapsParams) ([]Map, error)
 	// ListScriptPolicy implements listScriptPolicy operation.
 	//
 	// Get list of script policies.
diff --git a/pkg/api/oas_unimplemented_gen.go b/pkg/api/oas_unimplemented_gen.go
index 78953e1..738f398 100644
--- a/pkg/api/oas_unimplemented_gen.go
+++ b/pkg/api/oas_unimplemented_gen.go
@@ -229,6 +229,15 @@ func (UnimplementedHandler) DeleteScriptPolicy(ctx context.Context, params Delet
 	return ht.ErrNotImplemented
 }
 
+// GetMap implements getMap operation.
+//
+// Retrieve map with ID.
+//
+// GET /maps/{MapID}
+func (UnimplementedHandler) GetMap(ctx context.Context, params GetMapParams) (r *Map, _ error) {
+	return r, ht.ErrNotImplemented
+}
+
 // GetMapfix implements getMapfix operation.
 //
 // Retrieve map with ID.
@@ -274,6 +283,15 @@ func (UnimplementedHandler) ListMapfixes(ctx context.Context, params ListMapfixe
 	return r, ht.ErrNotImplemented
 }
 
+// ListMaps implements listMaps operation.
+//
+// Get list of maps.
+//
+// GET /maps
+func (UnimplementedHandler) ListMaps(ctx context.Context, params ListMapsParams) (r []Map, _ error) {
+	return r, ht.ErrNotImplemented
+}
+
 // ListScriptPolicy implements listScriptPolicy operation.
 //
 // Get list of script policies.
diff --git a/pkg/api/oas_validators_gen.go b/pkg/api/oas_validators_gen.go
index 7aca2dd..4dc04e6 100644
--- a/pkg/api/oas_validators_gen.go
+++ b/pkg/api/oas_validators_gen.go
@@ -8,6 +8,56 @@ import (
 	"github.com/ogen-go/ogen/validate"
 )
 
+func (s *Map) Validate() error {
+	if s == nil {
+		return validate.ErrNilPointer
+	}
+
+	var failures []validate.FieldError
+	if err := func() error {
+		if err := (validate.String{
+			MinLength:    0,
+			MinLengthSet: false,
+			MaxLength:    128,
+			MaxLengthSet: true,
+			Email:        false,
+			Hostname:     false,
+			Regex:        nil,
+		}).Validate(string(s.DisplayName)); err != nil {
+			return errors.Wrap(err, "string")
+		}
+		return nil
+	}(); err != nil {
+		failures = append(failures, validate.FieldError{
+			Name:  "DisplayName",
+			Error: err,
+		})
+	}
+	if err := func() error {
+		if err := (validate.String{
+			MinLength:    0,
+			MinLengthSet: false,
+			MaxLength:    128,
+			MaxLengthSet: true,
+			Email:        false,
+			Hostname:     false,
+			Regex:        nil,
+		}).Validate(string(s.Creator)); err != nil {
+			return errors.Wrap(err, "string")
+		}
+		return nil
+	}(); err != nil {
+		failures = append(failures, validate.FieldError{
+			Name:  "Creator",
+			Error: err,
+		})
+	}
+	if len(failures) > 0 {
+		return &validate.Error{Fields: failures}
+	}
+	return nil
+}
+
 func (s *Mapfix) Validate() error {
 	if s == nil {
 		return validate.ErrNilPointer