A back office for every app you ship.
Accounts in the CRM, support in the inbox, a phone number and Stripe billing, one workspace per project. Stop rebuilding the same backend for every client.
import { Kylosys } from "@kylosys/sdk";const kylosys = new Kylosys(process.env.KYLOSYS_KEY);// When someone signs upawait kylosys.contacts.create({ email: user.email, source: "signup",});// Let the team know, in the inbox they already useawait kylosys.notes.create({ contact: user.email, body: "New sign-up" });
# Settings › Channels › Emailfrom: support@acme.cato: acme-7k2p@inbox.kylosys.comstatus: receivingreplies: sent from support@acme.ca # after SPF + DKIM# Every email becomes a conversation in Inbox,# matched to the sender's contact record.
// POST https://api.acme.ca/kylosysapp.post("/kylosys", (req, res) => { if (!kylosys.webhooks.verify(req)) return res.sendStatus(401); const { type, data } = req.body; if (type === "ticket.created") notifyOnCall(data); if (type === "invoice.payment_recorded") markPaid(data); res.sendStatus(200);});
Three samples. Three jobs done.
Send sign-ups to the CRM, forward support email in, and listen for changes.
Send every sign-up to the CRM.
Create the contact with its source, then drop a note in the inbox your team already watches. No new dashboard to check.
import { Kylosys } from "@kylosys/sdk";const kylosys = new Kylosys(process.env.KYLOSYS_KEY);// When someone signs upawait kylosys.contacts.create({ email: user.email, source: "signup",});// Let the team know, in the inbox they already useawait kylosys.notes.create({ contact: user.email, body: "New sign-up" });
Forward support email in.
Point support@yourapp at your workspace address. Every email becomes a conversation in Inbox, matched to the sender's record. Replies go out from your own address after SPF and DKIM check out.
# Settings › Channels › Emailfrom: support@acme.cato: acme-7k2p@inbox.kylosys.comstatus: receivingreplies: sent from support@acme.ca # after SPF + DKIM# Every email becomes a conversation in Inbox,# matched to the sender's contact record.
Know the moment something changes.
Verify the signature, switch on the event type, return 200. Failed deliveries retry automatically and every attempt is logged with its response.
// POST https://api.acme.ca/kylosysapp.post("/kylosys", (req, res) => { if (!kylosys.webhooks.verify(req)) return res.sendStatus(401); const { type, data } = req.body; if (type === "ticket.created") notifyOnCall(data); if (type === "invoice.payment_recorded") markPaid(data); res.sendStatus(200);});
Everything the app does, your code can do.
Scoped keys
One key per workspace, limited to the resources it needs, rate-limited and revocable.
Signed webhooks
HMAC signatures, automatic retries and a delivery log you can replay from.
Sandbox
Test numbers and Stripe test mode. Nothing real gets called or charged.
One workspace per project
Each app or client gets separate customers, inboxes and numbers under one login.