diff --git a/code/__DEFINES/rust_g.dm b/code/__DEFINES/rust_g.dm
index ccd5b92c..614364b3 100644
--- a/code/__DEFINES/rust_g.dm
+++ b/code/__DEFINES/rust_g.dm
@@ -1,10 +1,27 @@
// rust_g.dm - DM API for rust_g extension library
#define RUST_G "rust_g"
+#define RUSTG_JOB_NO_RESULTS_YET "NO RESULTS YET"
+#define RUSTG_JOB_NO_SUCH_JOB "NO SUCH JOB"
+#define RUSTG_JOB_ERROR "JOB PANICKED"
+
#define rustg_dmi_strip_metadata(fname) call(RUST_G, "dmi_strip_metadata")(fname)
+#define rustg_dmi_create_png(fname,width,height,data) call(RUST_G, "dmi_create_png")(fname,width,height,data)
#define rustg_git_revparse(rev) call(RUST_G, "rg_git_revparse")(rev)
#define rustg_git_commit_date(rev) call(RUST_G, "rg_git_commit_date")(rev)
-#define rustg_log_write(fname, text) call(RUST_G, "log_write")(fname, text)
+#define rustg_log_write(fname, text, format) call(RUST_G, "log_write")(fname, text, format)
/proc/rustg_log_close_all() return call(RUST_G, "log_close_all")()
+
+// RUST-G defines & procs for HTTP component
+#define RUSTG_HTTP_METHOD_GET "get"
+#define RUSTG_HTTP_METHOD_POST "post"
+#define RUSTG_HTTP_METHOD_PUT "put"
+#define RUSTG_HTTP_METHOD_DELETE "delete"
+#define RUSTG_HTTP_METHOD_PATCH "patch"
+#define RUSTG_HTTP_METHOD_HEAD "head"
+
+#define rustg_http_request_blocking(method, url, body, headers) call(RUST_G, "http_request_blocking")(method, url, body, headers)
+#define rustg_http_request_async(method, url, body, headers) call(RUST_G, "http_request_async")(method, url, body, headers)
+#define rustg_http_check_request(req_id) call(RUST_G, "http_check_request")(req_id)
\ No newline at end of file
diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm
index 30740956..32955a59 100644
--- a/code/__HELPERS/_logging.dm
+++ b/code/__HELPERS/_logging.dm
@@ -5,6 +5,9 @@
#define SEND_TEXT(target, text) DIRECT_OUTPUT(target, text)
#define WRITE_FILE(file, text) DIRECT_OUTPUT(file, text)
#define WRITE_LOG(log, text) rustg_log_write(log, text)
+//This is an external call, "true" and "false" are how rust parses out booleans
+#define WRITE_LOG(log, text) rustg_log_write(log, text, "true")
+#define WRITE_LOG_NO_FORMAT(log, text) rustg_log_write(log, text, "false")
//print a warning message to world.log
#define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [src] usr: [usr].")
diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm
index 194ef1c2..ceb879d5 100644
--- a/code/controllers/configuration/entries/general.dm
+++ b/code/controllers/configuration/entries/general.dm
@@ -426,6 +426,8 @@
/datum/config_entry/string/default_view
config_entry_value = "15x15"
+/datum/config_entry/string/centcom_ban_db // URL for the CentCom Galactic Ban DB API
+
/datum/config_entry/flag/log_pictures
/datum/config_entry/flag/picture_logging_camera
diff --git a/code/datums/http.dm b/code/datums/http.dm
new file mode 100644
index 00000000..ba552cbb
--- /dev/null
+++ b/code/datums/http.dm
@@ -0,0 +1,74 @@
+/datum/http_request
+ var/id
+ var/in_progress = FALSE
+
+ var/method
+ var/body
+ var/headers
+ var/url
+
+ var/_raw_response
+
+/datum/http_request/proc/prepare(method, url, body = "", list/headers)
+ if (!length(headers))
+ headers = ""
+ else
+ headers = json_encode(headers)
+
+ src.method = method
+ src.url = url
+ src.body = body
+ src.headers = headers
+
+/datum/http_request/proc/execute_blocking()
+ _raw_response = rustg_http_request_blocking(method, url, body, headers)
+
+/datum/http_request/proc/begin_async()
+ if (in_progress)
+ CRASH("Attempted to re-use a request object.")
+
+ id = rustg_http_request_async(method, url, body, headers)
+
+ if (isnull(text2num(id)))
+ stack_trace("Proc error: [id]")
+ _raw_response = "Proc error: [id]"
+ else
+ in_progress = TRUE
+
+/datum/http_request/proc/is_complete()
+ if (isnull(id))
+ return TRUE
+
+ if (!in_progress)
+ return TRUE
+
+ var/r = rustg_http_check_request(id)
+
+ if (r == RUSTG_JOB_NO_RESULTS_YET)
+ return FALSE
+ else
+ _raw_response = r
+ in_progress = FALSE
+ return TRUE
+
+/datum/http_request/proc/into_response()
+ var/datum/http_response/R = new()
+
+ try
+ var/list/L = json_decode(_raw_response)
+ R.status_code = L["status_code"]
+ R.headers = L["headers"]
+ R.body = L["body"]
+ catch
+ R.errored = TRUE
+ R.error = _raw_response
+
+ return R
+
+/datum/http_response
+ var/status_code
+ var/body
+ var/list/headers
+
+ var/errored = FALSE
+ var/error
\ No newline at end of file
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index b0c9be04..5e662993 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -40,6 +40,11 @@
if(M.client)
body += "
\[First Seen: [M.client.player_join_date]\]\[Byond account registered on: [M.client.account_join_date]\]"
+ body += "
CentCom Galactic Ban DB: "
+ if(CONFIG_GET(string/centcom_ban_db))
+ body += "Search"
+ else
+ body += "Disabled"
body += "
Show related accounts by: "
body += "\[ CID | "
body += "IP \]"
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 62cb66f9..6b6e78f0 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -2498,6 +2498,60 @@
dat += thing_to_check
usr << browse(dat.Join("
"), "window=related_[C];size=420x300")
+ else if(href_list["centcomlookup"])
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(!CONFIG_GET(string/centcom_ban_db))
+ to_chat(usr, "Centcom Galactic Ban DB is disabled!")
+ return
+
+ var/ckey = href_list["centcomlookup"]
+
+ // Make the request
+ var/datum/http_request/request = new()
+ request.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/centcom_ban_db)]/[ckey]", "", "")
+ request.begin_async()
+ UNTIL(request.is_complete() || !usr)
+ if (!usr)
+ return
+ var/datum/http_response/response = request.into_response()
+
+ var/list/bans
+
+ var/list/dat = list("