Authentication and roles.
Public reads aside, the API asks who you are and what you may do. A request carries a credential, that credential resolves to a user, and the user has a role on the site being addressed. This page covers how to sign a request, how to obtain a token, and what each role is allowed.
Authentication is not enforced at the door. Every request runs the same way: if it carries a credential, the runtime resolves the user and their membership; if it does not, it continues as anonymous. Each endpoint then decides for itself. That is why a public read serves an anonymous caller, while a protected endpoint answers 401 when no credential is present, or 403 when the credential resolves to a role that is too low.
How a request is authenticated
There are two interchangeable ways to present a credential. Both carry the same token, and every endpoint accepts either.
- Bearer token. Send
Authorization: Bearer. This is how a server-side or command-line client authenticates. - Session cookie. The
current_usercookie, set by the login endpoint, carries the same token. A browser sends it automatically, so a page's ownfetchcalls are signed in without any extra header. An olderfs_sessioncookie is accepted as a fallback.
The token itself is a JSON Web Token: signed by the platform, with your user identifier as its subject. Treat it as opaque. You obtain it by logging in and then present it unchanged; you never construct or decode it to call the API.
Logging in
Exchange an email and password for a token at POST /api/v1/auth/login (also reachable at /auth/login). The endpoint is public and rate limited. The login is scoped to the site host you send it to, so a user signs in on their own site.
curl -X POST https://your-site.fleeksite.com/api/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"email": "you@example.com", "password": "your-password"}'A successful login returns the token at data.token and, in a browser, also sets the current_user cookie:
{ "data": { "text": "Welcome!", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }, "state": "ok" }From there, send the token as a bearer credential on any authenticated call:
curl https://your-site.fleeksite.com/api/v1/leads \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'Bad credentials return 401 with a message at data.text; a disabled account returns 403. From a browser you can skip the header entirely and rely on the cookie the login set.
Other ways to sign in
Login is the common path, but the platform offers a few alternatives, all under the same auth prefix and all returning or setting the same token:
- Sign-up.
POST /api/v1/auth/signupregisters a new user (at the base role) and returns a token exactly as login does. - Email code. A passwordless flow:
POST /api/v1/auth/login/codeemails a one-time code, andPOST /api/v1/auth/login/verifyexchanges the code for a token. - Social login. OAuth sign-in with Facebook, Google and Twitter is available under the
/auth/prefix. Each finds or creates the user and returns the same kind of token; the provider-specific flow is out of scope here.
Password reset and email verification live under the same prefix. All of these are public entry points, since a person cannot yet be authenticated when they use them.
The role model
A user has a numeric role. Higher is more permission. These are the role numbers and names the platform uses:
| Role | Name | Typically |
|---|---|---|
1 | customer | A registered visitor, buyer or commenter. |
2 | writer | Contributes content. |
3 | marketer | Manages content, leads, orders and site tooling. |
4 | designer | Works on templates and presentation. |
5 | admin | Manages site settings. |
7 | super admin | Platform staff, who act across sites. |
Reads of published content need no role at all. The line falls between reading content, which is public, and everything else, which needs a credential and usually a role. The main threshold is role 3: it is where managing the site, and reading the data that identifies people, begins.
| To do this | You need |
|---|---|
| Read posts, templates, bits, files, comments, redirects and the product catalogue | nothing (public) |
| Submit a lead, quote a discount, hold an anonymous cart | nothing (public) |
| Create content, read your own orders, post a comment | session |
| Manage content, redirects and bits; read leads and orders; manage plugins and webhooks; presign an upload; read logs | role 3+ |
| List site users | role 2+ |
| Update site settings; send a notification | role 5+ |
| Delete a site | owner or role 7+ |
Many write endpoints also let the record's own author act on it regardless of a low role. That is what owner or role 3+ means in the API tables: the person who created the post, template or file can edit it, and so can anyone at role 3 or above.
A role is scoped to one site. A membership belongs to a single site, so the role a request is granted is the caller's role on the site being addressed, not on whichever site their account was created. A token minted elsewhere grants no role here unless that same person also holds a membership on this site. Platform staff (role 7 and above) are the deliberate exception: they carry their role across sites.
current_user in a template
The same principal is exposed to your Liquid as current_user. On an anonymous request it is empty, so it doubles as the signed-in test:
{% if current_user %}
>Signed in as {{ current_user.name }}.
>
{% else %}
href="/login">Sign in>
{% endif %}current_user.role is the site-scoped role: the caller's membership role on the site being rendered, following the same rule as the API. A visitor with no membership on this site carries no elevated role, so a role gate in a template reliably fences off staff-only content:
{% if current_user.role > 2 %}
href="/admin/content">Manage content>
{% endif %}Because the role is resolved per site, the same account can be an admin on one site and an ordinary visitor on another, and the template sees whichever applies to the site it is rendering. Continue to Validate and deploy to edit a template, check it and ship the change.