diff --git a/docs/api.md b/docs/api.md
index c307bdbf89312121a1963fc01c2fd83b96010c26..25f04517bcffc801abae4b6fdd4e9115dc2f039a 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -10,6 +10,36 @@ API access is granted only authenticated you need to supply an Authorization hea
 Authorization: Bearer <API-Key>
 ```
 
+## `POST /api/json/key/create`
+
+Creates a key and charges it by specified amount. Creates a Order to do so. A note can be attached to the Order.  
+`manual` is currently the only valid payment processor for API.  
+Can take either amount or price. If both supplied only amount is taken into account.
+
+### Parameters
+
+```json
+{
+    "amount": <AMOUNT_TO_CHARGE>,
+    "price": <PRICE_TO_CHARGE>,
+    "payment_processor": "manual",
+    "note": <NOTE_FOR_ORDER>
+}
+```
+
+### Example Response
+
+Successfull discharge will have a response code of `201`  
+If the key cannot be charged because it is already charged with too many Orders response code will be `403`
+
+```json
+{
+    "key": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
+    "order_id": 123456,
+    "charged": <AMOUNT_CHARGED>
+}
+```
+
 ## `GET /api/json/key/:key`
 
 Retrieves detailed information for a given key.
@@ -83,7 +113,7 @@ If the key cannot be charged because it is already charged with too many Orders
 ```json
 {
     "key": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
-    "charge": 100,
+    "order_id": 123456,
     "charged": <AMOUNT_CHARGED>
 }
 ```
diff --git a/pass/app/Key.js b/pass/app/Key.js
index e19f5d636191df0f1d15e8edc42a180d4820d67b..3554a17d7a18068348eeb3b4adabf2fce1750f76 100644
--- a/pass/app/Key.js
+++ b/pass/app/Key.js
@@ -358,23 +358,21 @@ class Key {
 
   /**
    *
-   * @returns A new MetaGer-Pass Key with 0 searches
+   * @returns {Promise<Key>} A new MetaGer-Pass Key with 0 searches
    */
   static async GET_NEW_KEY() {
-    return new Promise(async (resolve, reject) => {
-      let redis_client = RedisClient.CLIENT();
-      let crypto = require("crypto");
-      do {
-        let key = crypto.randomUUID();
+    let redis_client = RedisClient.CLIENT();
+    let crypto = require("crypto");
+    do {
+      let key = crypto.randomUUID();
 
-        let key_exists = await redis_client.exists(Key.DATABASE_PREFIX + key);
-        if (!key_exists) {
-          await redis_client.quit();
-          return resolve(key);
-        }
-        await new Promise((resolve) => setTimeout(resolve, 50));
-      } while (true);
-    });
+      let key_exists = await redis_client.exists(Key.DATABASE_PREFIX + key);
+      if (!key_exists) {
+        await redis_client.quit();
+        return Key.GET_KEY(key);
+      }
+      await new Promise((resolve) => setTimeout(resolve, 50));
+    } while (true);
   }
 }
 
diff --git a/pass/routes/api.js b/pass/routes/api.js
index 5bb9d65702223e0ebd71efb5486ccfd24feae8e0..23793e2c89de777005836ae493556aae9f67c7e5 100644
--- a/pass/routes/api.js
+++ b/pass/routes/api.js
@@ -26,6 +26,51 @@ router.use((req, res, next) => {
   }
 });
 
+router.post("/key/create", (req, res) => {
+  let amount = req.body.amount;
+  if (!amount) {
+    // If amount is not given but price is
+    // Calculate amount from price
+    let price = req.body.price;
+    if (price) {
+      amount = Math.ceil((price / config.get("price.per_300")) * 300);
+    } else {
+      res.status(403).json({
+        code: 403,
+        error: "Either :amount or :price must be supplied.",
+      });
+      return;
+    }
+  }
+  let note = req.body.note ?? "";
+  /**
+   * @type {Order}
+   */
+  let new_order;
+  Key.GET_NEW_KEY()
+    .then((key) =>
+      Order.CREATE_NEW_ORDER(amount, key.get_key(), new Manual(note))
+    )
+    .then((order) => {
+      new_order = order;
+      return new_order.captureOrder();
+    })
+    .then(() => new_order.chargeKey())
+    .then(async () => {
+      res.status(201).json({
+        key: await new_order.getKeyFromOrderLink(),
+        order_id: new_order.getOrderID(),
+        charged: new_order.getAmount(),
+      });
+    })
+    .catch((reason) => {
+      res.status(403).json({
+        code: 403,
+        error: "Cannot create Order for given Key",
+      });
+    });
+});
+
 router.get("/key/:key", (req, res) => {
   Key.GET_KEY(req.params.key, false).then((key) => {
     res.json({
diff --git a/pass/routes/key.js b/pass/routes/key.js
index 8e3f5d0b658180664ad322b7af8aed54f962cb56..1c1c64d0047d37db1bcd60c661773cbe7689fc80 100644
--- a/pass/routes/key.js
+++ b/pass/routes/key.js
@@ -1,10 +1,16 @@
 var express = require("express");
 var router = express.Router();
-var multer = require('multer');
-const { param, body, check, oneOf, validationResult, matchedData } = require("express-validator");
+var multer = require("multer");
+const {
+  param,
+  body,
+  check,
+  oneOf,
+  validationResult,
+  matchedData,
+} = require("express-validator");
 const config = require("config");
 
-
 var orderRouter = require("./orders/orders");
 var checkout_router_paypal = require("./checkout/paypal");
 var checkout_router_manual = require("./checkout/manual");
@@ -13,7 +19,7 @@ var Key = require("../app/Key");
 
 router.get("/create", function (req, res, next) {
   Key.GET_NEW_KEY().then((key) => {
-    res.redirect(`${res.locals.baseDir}/key/` + key + "?new=true");
+    res.redirect(`${res.locals.baseDir}/key/` + key.get_key() + "?new=true");
   });
 });
 
@@ -22,11 +28,13 @@ router.get("/remove", (req, res) => {
     res.clearCookie("key");
   }
   res.redirect("/");
-})
+});
 
 router.get("/enter", function (req, res, next) {
   if (req.cookies.key) {
-    res.redirect(`${res.locals.baseDir}/key/` + encodeURIComponent(req.cookies.key));
+    res.redirect(
+      `${res.locals.baseDir}/key/` + encodeURIComponent(req.cookies.key)
+    );
   } else {
     res.render("login/key");
   }
@@ -38,11 +46,15 @@ const upload = multer({
   limits: {
     fileSize: 5 * 1024 * 1024,
     files: 1,
-    fields: 1
-  }
+    fields: 1,
+  },
 });
-router.post("/enter", upload.single('file'),
-  body("key").customSanitizer(value => Key.GET_KEY(value).then(key => key.get_key())),
+router.post(
+  "/enter",
+  upload.single("file"),
+  body("key").customSanitizer((value) =>
+    Key.GET_KEY(value).then((key) => key.get_key())
+  ),
   function (req, res, next) {
     const errors = validationResult(req);
     if (!errors.isEmpty()) {
@@ -56,7 +68,7 @@ router.post("/enter", upload.single('file'),
     } else if (typeof req.file === "undefined") {
       res.render("login/key", { errors: "File not provided or invalid" });
     } else {
-      const jimp = require('jimp');
+      const jimp = require("jimp");
 
       jimp.read(req.file.buffer, (err, image) => {
         if (err) {
@@ -79,7 +91,9 @@ router.post("/enter", upload.single('file'),
           }
           let key = url.searchParams.get("key");
           if (key !== null) {
-            res.redirect(`${res.locals.baseDir}/key/` + encodeURIComponent(key));
+            res.redirect(
+              `${res.locals.baseDir}/key/` + encodeURIComponent(key)
+            );
           } else {
             res.render("login/key", { errors: ["Error parsing URL"] });
           }
@@ -87,8 +101,8 @@ router.post("/enter", upload.single('file'),
         qr.decode(image.bitmap);
       });
     }
-
-  });
+  }
+);
 
 router.use("/:key", param("key").isUUID(4), async (req, res, next) => {
   // Input Validation
@@ -102,13 +116,16 @@ router.use("/:key", param("key").isUUID(4), async (req, res, next) => {
     encodeURIComponent(req.params.key);
   let QRCode = require("qrcode");
 
-  let qr_data_uri = await QRCode.toDataURL(metager_url, { errorCorrectionLevel: 'H', scale: 8 });
+  let qr_data_uri = await QRCode.toDataURL(metager_url, {
+    errorCorrectionLevel: "H",
+    scale: 8,
+  });
 
-  Key.GET_KEY(req.params.key, false).then(key => {
+  Key.GET_KEY(req.params.key, false).then((key) => {
     req.data = Object.assign(req.data, {
       created_new: req.query.new === "true" ? true : false,
       price: {
-        per_300: config.get("price.per_300")
+        per_300: config.get("price.per_300"),
       },
       key: {
         key: key,
@@ -133,9 +150,12 @@ router.get("/:key", async (req, res) => {
   if (req.data.admin) {
     res.redirect(`${res.locals.baseDir}/logout`);
     return;
-  } else if (!req.cookies.key || req.cookies.key !== req.data.key.key.get_key()) {
+  } else if (
+    !req.cookies.key ||
+    req.cookies.key !== req.data.key.key.get_key()
+  ) {
     res.cookie("key", req.data.key.key.get_key(), {
-      sameSite: "lax"
+      sameSite: "lax",
     });
   }
   res.render("key", req.data);
@@ -171,7 +191,10 @@ router.use(
 
     // Add a URL to change the checkout amount
     req.data.change_url = {
-      amount: `${res.locals.baseDir}/key/` + encodeURIComponent(req.data.key.key.get_key()) + "#charge",
+      amount:
+        `${res.locals.baseDir}/key/` +
+        encodeURIComponent(req.data.key.key.get_key()) +
+        "#charge",
     };
 
     next("route");