/api
HTTP
Anything that speaks HTTP
Ordinary requests from scripts, integrations and the tools your team already runs.
The short version: your data is isolated below the business logic, permissions are explicit grants rather than job titles, nothing is truly deleted, and every operation is recorded.
Multi-tenant systems usually isolate customers in application code — every query is supposed to include a filter for the right company. It works until one query forgets.
emko cloud doesn't rely on remembering. Tenant scoping is applied one layer below the business logic, inside the component that talks to the database. Every retrieve, list, count, update and delete is scoped before it runs. A feature cannot forget the filter, because a feature never writes the filter.
Defence in depth: even if business logic has a bug, the data layer prevents cross-company access. Every record type in the system — all of them, with no exemptions — sits inside this boundary.
There is no role table, and that's deliberate. A "Sales Manager" at one company holds a completely different set of powers than a "Sales Manager" at another. The label is the same; the permissions aren't. Naming the label and pretending it means something is how access control quietly stops matching the org chart.
Instead, each user carries explicit grants: a resource, an action, and the constraints that apply.
Constraints can scope a grant to a company, a team, a project, a specific record, a set of statuses, or a time window — nested so that company-wide access implies project access implies access to your own records.
Two consequences worth knowing:
Deletes mark records as deleted rather than removing them. Deleted data stays recoverable, history stays intact, and reports over past periods keep working.
Cascades are explicit and controlled by the application rather than the database, specifically so that a cascade can never chase a reference across a company boundary.
Two independent trails run under every operation:
Every record's identifier names its own type. A person's ID is visibly a person's ID; a project's is visibly a project's. Two consequences show up in daily use:
Companies also carry a short, human-readable public ID — the one your people type on the sign-in form, rather than a UUID nobody can read over the phone.
Every operation is published on four surfaces at once. Not four integrations maintained in parallel — one catalogue of operations with four protocols in front of it. Add a record type and it appears on all four the same day.
/api
Anything that speaks HTTP
Ordinary requests from scripts, integrations and the tools your team already runs.
/rpc
One endpoint, every operation
Typed end to end. It is what the product's own screens call.
/mcp
Every operation as an AI tool
For our assistant, and for yours. No separate integration to build.
/ws
Live change events
Subscribe by record type and see writes as they happen.
The security point matters more than the convenience one. These are not four implementations that each have to remember the rules — they are four doors into the same catalogue, behind the same permission check and the same tenant scoping.
emko cloud is one process. The public site and the signed-in application share a single server on a single origin. There is no separate frontend server, no bundler running in production, no orchestration layer.
Run it on your own hardware, in your own jurisdiction, with your data on your disk. Or let us run it.