Index: /binary-improvements2/7dtd-server-fixes/src/JSON/JSONBoolean.cs
===================================================================
--- /binary-improvements2/7dtd-server-fixes/src/JSON/JSONBoolean.cs	(revision 388)
+++ /binary-improvements2/7dtd-server-fixes/src/JSON/JSONBoolean.cs	(revision 389)
@@ -34,4 +34,8 @@
 			throw new MalformedJSONException ("No valid boolean found");
 		}
+
+		public override string AsString => value ? "true" : "false";
+		public override int AsInt => value ? 1 : 0;
+		public override double AsDouble => AsInt;
 	}
 }
Index: /binary-improvements2/7dtd-server-fixes/src/JSON/JSONNull.cs
===================================================================
--- /binary-improvements2/7dtd-server-fixes/src/JSON/JSONNull.cs	(revision 388)
+++ /binary-improvements2/7dtd-server-fixes/src/JSON/JSONNull.cs	(revision 389)
@@ -1,2 +1,3 @@
+using System;
 using System.Text;
 
@@ -18,4 +19,8 @@
 			return new JSONNull ();
 		}
+
+		public override string AsString => throw new NotSupportedException ();
+		public override int AsInt => throw new NotSupportedException ();
+		public override double AsDouble => throw new NotSupportedException ();
 	}
 }
Index: /binary-improvements2/7dtd-server-fixes/src/JSON/JSONNumber.cs
===================================================================
--- /binary-improvements2/7dtd-server-fixes/src/JSON/JSONNumber.cs	(revision 388)
+++ /binary-improvements2/7dtd-server-fixes/src/JSON/JSONNumber.cs	(revision 389)
@@ -109,4 +109,8 @@
 			throw new MalformedJSONException ("End of JSON reached before parsing number finished");
 		}
+
+		public override string AsString => value.ToCultureInvariantString ();
+		public override int AsInt => GetInt ();
+		public override double AsDouble => value;
 	}
 }
Index: /binary-improvements2/7dtd-server-fixes/src/JSON/JSONObject.cs
===================================================================
--- /binary-improvements2/7dtd-server-fixes/src/JSON/JSONObject.cs	(revision 388)
+++ /binary-improvements2/7dtd-server-fixes/src/JSON/JSONObject.cs	(revision 389)
@@ -7,18 +7,18 @@
 
 		public JSONNode this [string _name] {
-			get { return nodes [_name]; }
-			set { nodes [_name] = value; }
+			get => nodes [_name];
+			set => nodes [_name] = value;
 		}
 
-		public int Count {
-			get { return nodes.Count; }
-		}
+		public int Count => nodes.Count;
 
-		public List<string> Keys {
-			get { return new List<string> (nodes.Keys); }
-		}
+		public List<string> Keys => new List<string> (nodes.Keys);
 
 		public bool ContainsKey (string _name) {
 			return nodes.ContainsKey (_name);
+		}
+
+		public bool TryGetValue (string _name, out JSONNode _node) {
+			return nodes.TryGetValue (_name, out _node);
 		}
 
Index: /binary-improvements2/7dtd-server-fixes/src/JSON/JSONString.cs
===================================================================
--- /binary-improvements2/7dtd-server-fixes/src/JSON/JSONString.cs	(revision 388)
+++ /binary-improvements2/7dtd-server-fixes/src/JSON/JSONString.cs	(revision 389)
@@ -114,4 +114,8 @@
 			throw new MalformedJSONException ("End of JSON reached before parsing string finished");
 		}
+
+		public override string AsString => value;
+		public override int AsInt => int.Parse (value);
+		public override double AsDouble => double.Parse (value);
 	}
 }
Index: /binary-improvements2/7dtd-server-fixes/src/JSON/JSONValue.cs
===================================================================
--- /binary-improvements2/7dtd-server-fixes/src/JSON/JSONValue.cs	(revision 388)
+++ /binary-improvements2/7dtd-server-fixes/src/JSON/JSONValue.cs	(revision 389)
@@ -1,4 +1,7 @@
 ﻿namespace AllocsFixes.JSON {
 	public abstract class JSONValue : JSONNode {
+		public abstract string AsString { get; }
+		public abstract int AsInt { get; }
+		public abstract double AsDouble { get; }
 	}
 }
Index: /binary-improvements2/MapRendering/Web/API/AbsRestApi.cs
===================================================================
--- /binary-improvements2/MapRendering/Web/API/AbsRestApi.cs	(revision 388)
+++ /binary-improvements2/MapRendering/Web/API/AbsRestApi.cs	(revision 389)
@@ -105,4 +105,23 @@
 		}
 
+		protected bool TryGetJsonField (JSONObject _body, string _fieldName, out int _value) {
+			_value = default;
+			
+			if (!_body.TryGetValue (_fieldName, out JSONNode fieldNode)) {
+				return false;
+			}
+
+			if (!(fieldNode is JSONValue valueField)) {
+				return false;
+			}
+
+			try {
+				_value = valueField.AsInt;
+				return true;
+			} catch (Exception) {
+				return false;
+			}
+		}
+
 		protected abstract void HandleRestGet (RequestContext _context);
 
Index: /binary-improvements2/MapRendering/Web/Handlers/ApiHandler.cs
===================================================================
--- /binary-improvements2/MapRendering/Web/Handlers/ApiHandler.cs	(revision 388)
+++ /binary-improvements2/MapRendering/Web/Handlers/ApiHandler.cs	(revision 389)
@@ -22,20 +22,19 @@
 			Object[] apiEmptyCtorArgs = { };
 			
-			foreach (Type t in Assembly.GetExecutingAssembly ().GetTypes ()) {
-				if (!t.IsAbstract && t.IsSubclassOf (typeof (AbsWebAPI))) {
-					ConstructorInfo ctor = t.GetConstructor (apiWithParentCtorTypes);
-					if (ctor != null) {
-						AbsWebAPI apiInstance = (AbsWebAPI) ctor.Invoke (apiWithParentCtorArgs);
-						addApi (apiInstance);
-						continue;
-					}
+			
+			ReflectionHelpers.FindTypesImplementingBase (typeof (AbsWebAPI), _type => {
+				ConstructorInfo ctor = _type.GetConstructor (apiWithParentCtorTypes);
+				if (ctor != null) {
+					AbsWebAPI apiInstance = (AbsWebAPI) ctor.Invoke (apiWithParentCtorArgs);
+					addApi (apiInstance);
+					return;
+				}
 					
-					ctor = t.GetConstructor (apiEmptyCtorTypes);
-					if (ctor != null) {
-						AbsWebAPI apiInstance = (AbsWebAPI) ctor.Invoke (apiEmptyCtorArgs);
-						addApi (apiInstance);
-					}
+				ctor = _type.GetConstructor (apiEmptyCtorTypes);
+				if (ctor != null) {
+					AbsWebAPI apiInstance = (AbsWebAPI) ctor.Invoke (apiEmptyCtorArgs);
+					addApi (apiInstance);
 				}
-			}
+			});
 
 			// Permissions that don't map to a real API
Index: /binary-improvements2/MapRendering/Web/WebUtils.cs
===================================================================
--- /binary-improvements2/MapRendering/Web/WebUtils.cs	(revision 388)
+++ /binary-improvements2/MapRendering/Web/WebUtils.cs	(revision 389)
@@ -25,5 +25,5 @@
 			netWriteSampler.Begin ();
 #endif
-			WriteText (_resp, sb.ToString(), _mimeType: MimeJson);
+			WriteText (_resp, sb.ToString(), _statusCode, MimeJson);
 #if ENABLE_PROFILER
 			netWriteSampler.End ();
@@ -32,11 +32,11 @@
 
 		public static void WriteText (HttpListenerResponse _resp, string _text, HttpStatusCode _statusCode = HttpStatusCode.OK, string _mimeType = null) {
+			_resp.StatusCode = (int)_statusCode;
+			_resp.ContentType = _mimeType ?? MimePlain;
+			_resp.ContentEncoding = Encoding.UTF8;
+
 			byte[] buf = Encoding.UTF8.GetBytes (_text);
 			_resp.ContentLength64 = buf.Length;
 			_resp.OutputStream.Write (buf, 0, buf.Length);
-			
-			_resp.ContentType = _mimeType ?? MimePlain;
-			_resp.ContentEncoding = Encoding.UTF8;
-			_resp.StatusCode = (int)_statusCode;
 		}
 
