Start here
How access works
Kinds, roles, rules, apps and keys, and why your code never has to keep one customer's records away from another's.
Your account's own database
Each Awesomate account has its own database. It holds the account's contacts and any kinds you define: the tables an app keeps, such as jobs, quotes or messages. A kind has attributes (its columns) and links (to a contact, or to another kind). A record's links read back as <link>_id: a job linked to its customer has customer_id.
People and roles
The people who sign in to your apps are app users. Each has an email address and a role: owner, staff, member, or a role of your own. When you add someone, they are linked to the contact in your Contacts with the same email address, and if there is none yet, again each time they sign in.
Rules
Each kind has a read rule and a write rule for each role. A rule is one of these, or several joined with |:
| Rule | Means |
|---|---|
all |
Every record of the kind. |
none |
Nothing. A role with no rule gets this. |
own |
Records this person created. |
linked:customer |
Records whose customer link is this person's contact. |
linked:job.customer |
Records linked to a job whose customer is this person (up to three steps). |
For a customer portal, jobs and their messages:
{
"job": {
"read": { "member": "linked:customer", "staff": "all" },
"write": { "staff": "all" }
},
"message": {
"read": { "member": "linked:job.customer", "staff": "all" },
"write": { "member": "linked:job.customer", "staff": "all" }
}
}Until you set rules, owner and staff can do everything with a kind and members nothing. A write must leave the record inside the person's rule, so a customer cannot move their message onto someone else's job. Set rules with Claude Code (awesomate_crm_kinds, action set_access).
The database applies them, everywhere
Rules are compiled into the database's own row-level security. Every read, every write, every live list and every who's here check runs as the signed-in person, so the database returns only what their rule allows. Your page cannot ask for more, and a mistake in your code cannot show one customer another's job.
The same holds for things built on top. The app's AI assistant reads as the customer it is answering, and the voice agent is briefed only with records the person can see.
Some fields can be hidden from some roles even on a record they can read, such as a cost or a staff note on a customer's job. The database returns null for them, and refuses a write to them.
Things a rule would not allow
Sometimes a customer should do one specific thing their write rule does not allow, such as accept their own quote without being able to edit the job. A write recipe opened to their role does exactly that, and nothing else. See Let customers take an action.
Apps and keys
An app is a web page or mobile app your people sign in to. It has a name (used in the sign-in email), the addresses it runs on, a sign-up mode, and a publishable key (pk_). The key names the app and is not a secret. It goes in your page's code. A request from an address the app does not list is refused.
| Key | Looks like | Where it goes | What it can do |
|---|---|---|---|
| Publishable key | pk_... |
Browser code | Sign people in to one app. Every call then runs as them. |
| App server key | ak_... |
Your server or n8n, as a secret | Read and write records of the kinds it was made for. |
| Account token | amt_pat_... |
Your own machine or server, as a secret | Everything the account can do, including defining kinds. |
The SDK refuses an account token in the app client, and the hub refuses a server key from a browser.
Plans
| Essentials | Support Plus | Pro | Embedded | |
|---|---|---|---|---|
| Read your data, run saved queries | Yes | Yes | Yes | Yes |
| Define kinds, write records, server keys that write | Yes | Yes | Yes | |
| Apps your people sign in to | Yes | Yes |
All of this builds on Contacts, which is reaching accounts in stages. If it isn't on your account yet, the hub says so.