diff --git a/packages/builder/src/components/settings/Modal.svelte b/packages/builder/src/components/settings/Modal.svelte
index 2d832481c3..dc6809f488 100644
--- a/packages/builder/src/components/settings/Modal.svelte
+++ b/packages/builder/src/components/settings/Modal.svelte
@@ -1,5 +1,5 @@
+
+
API Keys
+
+
+
diff --git a/packages/builder/src/components/settings/tabs/index.js b/packages/builder/src/components/settings/tabs/index.js
index a1d1df38e4..6e34141d09 100644
--- a/packages/builder/src/components/settings/tabs/index.js
+++ b/packages/builder/src/components/settings/tabs/index.js
@@ -2,4 +2,5 @@ export { default as General } from "./General.svelte"
export { default as Integrations } from "./Integrations.svelte"
export { default as Permissions } from "./Permissions.svelte"
export { default as Users } from "./Users.svelte"
+export { default as APIKeys } from "./APIKeys.svelte"
export { default as DangerZone } from "./DangerZone.svelte"
diff --git a/packages/server/src/api/controllers/apikeys.js b/packages/server/src/api/controllers/apikeys.js
new file mode 100644
index 0000000000..35fc29e37e
--- /dev/null
+++ b/packages/server/src/api/controllers/apikeys.js
@@ -0,0 +1,52 @@
+const fs = require("fs")
+const readline = require("readline")
+const { budibaseAppsDir } = require("../../utilities/budibaseDir")
+const ENV_FILE_PATH = "/.env"
+
+exports.fetch = async function(ctx) {
+ ctx.status = 200
+ ctx.body = {
+ budibase: process.env.BUDIBASE_API_KEY,
+ sendgrid: process.env.SENDGRID_API_KEY,
+ }
+}
+
+exports.update = async function(ctx) {
+ const key = `${ctx.params.key.toUpperCase()}_API_KEY`
+ const value = ctx.request.body.value
+ // Set process.env
+ process.env[key] = value
+
+ // Write to file
+ await updateValues([key, value])
+
+ ctx.status = 200
+ ctx.message = `Updated ${ctx.params.key} API key succesfully.`
+ ctx.body = { [ctx.params.key]: ctx.request.body.value }
+}
+
+async function updateValues([key, value]) {
+ let newContent = ""
+ let keyExists = false
+ const readInterface = readline.createInterface({
+ input: fs.createReadStream(`${budibaseAppsDir()}/${ENV_FILE_PATH}`),
+ output: process.stdout,
+ console: false,
+ })
+ readInterface.on("line", function(line) {
+ // Mutate lines and change API Key
+ if (line.startsWith(key)) {
+ line = `${key}=${value}`
+ keyExists = true
+ }
+ newContent = `${newContent}\n${line}`
+ })
+ readInterface.on("close", function() {
+ // Write file here
+ if (!keyExists) {
+ // Add API Key if it doesn't exist in the file at all
+ newContent = `${newContent}\n${key}=${value}`
+ }
+ fs.writeFileSync(`${budibaseAppsDir()}/${ENV_FILE_PATH}`, newContent)
+ })
+}
diff --git a/packages/server/src/api/index.js b/packages/server/src/api/index.js
index e6143d6725..911b8f7c66 100644
--- a/packages/server/src/api/index.js
+++ b/packages/server/src/api/index.js
@@ -17,6 +17,7 @@ const {
componentRoutes,
workflowRoutes,
accesslevelRoutes,
+ apiKeysRoutes,
} = require("./routes")
const router = new Router()
@@ -98,6 +99,9 @@ router.use(clientRoutes.allowedMethods())
router.use(accesslevelRoutes.routes())
router.use(accesslevelRoutes.allowedMethods())
+router.use(apiKeysRoutes.routes())
+router.use(apiKeysRoutes.allowedMethods())
+
router.use(staticRoutes.routes())
router.use(staticRoutes.allowedMethods())
diff --git a/packages/server/src/api/routes/apikeys.js b/packages/server/src/api/routes/apikeys.js
new file mode 100644
index 0000000000..bec9ab677c
--- /dev/null
+++ b/packages/server/src/api/routes/apikeys.js
@@ -0,0 +1,12 @@
+const Router = require("@koa/router")
+const controller = require("../controllers/apikeys")
+const authorized = require("../../middleware/authorized")
+const { BUILDER } = require("../../utilities/accessLevels")
+
+const router = Router()
+
+router
+ .get("/api/keys", authorized(BUILDER), controller.fetch)
+ .put("/api/keys/:key", authorized(BUILDER), controller.update)
+
+module.exports = router
diff --git a/packages/server/src/api/routes/index.js b/packages/server/src/api/routes/index.js
index b50fee788a..50a652b39e 100644
--- a/packages/server/src/api/routes/index.js
+++ b/packages/server/src/api/routes/index.js
@@ -11,6 +11,7 @@ const staticRoutes = require("./static")
const componentRoutes = require("./component")
const workflowRoutes = require("./workflow")
const accesslevelRoutes = require("./accesslevel")
+const apiKeysRoutes = require("./apikeys")
module.exports = {
authRoutes,
@@ -26,4 +27,5 @@ module.exports = {
componentRoutes,
workflowRoutes,
accesslevelRoutes,
+ apiKeysRoutes,
}