Guide
Authentication
Every request authenticates with a personal API key sent as a bearer token. A key acts as the person who created it: it can never see or do more than they can in PRESHos, and its scopes can restrict it further.
Send the key in the Authorization header of every request. Keys look like preshos_v1_<lookup>_<secret>.
curl https://api.preshos.com/v1/me \
-H "Authorization: Bearer $PRESHOS_API_KEY"const API = 'https://api.preshos.com/v1';
const response = await fetch(`${API}/me`, {
headers: { Authorization: `Bearer ${process.env.PRESHOS_API_KEY}` },
});
const body = await response.json();
if (!response.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
console.log(body.data.user.name, body.data.api_key.scopes);GET /v1/me needs no scope. It returns the user the key acts as, the workspace, the key's scopes and expiry, and your rate limit, so it is the quickest way to check that a key works.
Creating keys requires developer access: the API Keys → Create permission. Workspace owners and admins have it. Standard members do not have it by default. An admin enables developers by granting API Keys → Create (own) to a role in Settings → Roles.
Developer access is checked on every request, not only when a key is created. If it is removed from your role, or your account is deactivated, every key you created stops working on its next request (403 developer_access_revoked or 401 api_key_user_inactive).
Admins with workspace-wide API Keys access see every key in the workspace under Settings → Developer → All workspace keys and can revoke any of them.
- In PRESHos, open Settings → Developer.
- Choose Create API key. Name it after the integration that will use it (for example "CRM sync") and add an optional description.
- Pick a scope preset or individual scopes, and an expiry.
- Copy the key from the confirmation dialog. It is shown once. PRESHos cannot show it again; if you lose it, create a new key.
- Store the key in a secret manager or your deployment's environment variables, then verify it with
GET /v1/me.
Every key expires: choose 7, 30, 90 (the default), 180, or 365 days. You can hold up to 25 active keys.
Scopes cap what a key may do. They never add permission: each request is allowed only if your PRESHos role permits it and the key has the scope. Changing your role takes effect on the next request.
| Scope | Allows | Endpoints |
|---|---|---|
records:read | Read records. Object schema, records, search, aggregates, relationships, and workflows. | 10 |
records:write | Write records. Create and update records, change status, link records, and batch edits. | 6 |
records:delete | Delete records. Permanently delete records. | 1 |
comments:read | Read comments. Record comment threads. | 1 |
comments:write | Post comments. Comment on records as you. | 1 |
users:read | Read members. Workspace members and teams. | 3 |
GET /v1/me needs no scope. A request without the required scope fails with 403 insufficient_scope; error.details.missing_scopes names what is missing. Each endpoint's scopes are listed in the API reference.
Settings → Developer offers three presets. You can also pick scopes individually.
| Preset | Scopes | Use for |
|---|---|---|
| Read only | records:read, comments:read, users:read | Reporting, exports, dashboards, and trying the API in Swagger UI. |
| Read & write | records:read, records:write, comments:read, comments:write, users:read | Sync jobs and integrations that create and update records. |
| Full access | records:read, records:write, records:delete, comments:read, comments:write, users:read | Integrations that must also delete records. |
A key is its user. Object, record, and field permissions from that user's roles apply to every call:
- Lists and searches only return records the user may read: their own records, their teams' records, or the whole workspace, depending on their role.
- A record the user cannot read returns
404 record_not_found, so ids do not reveal whether a record exists. - Fields the user cannot read are left out of
fields. Filtering, sorting, or selecting on them fails with403 permission_denied. - Writes are checked like writes in the app, including field-level edit permissions.
See Objects & records for how to discover what the user can do before you call.
- The raw key is shown once and is never stored or logged.
- PRESHos stores only an HMAC-SHA256 digest of the key, computed with a per-workspace secret held in the Secrets Vault (Google Cloud Secret Manager). A copy of the database alone cannot recover or verify a key.
- Every request re-checks the key: it exists and verifies, is not revoked or expired, its user is active and still a member, the workspace is active, the user still has developer access, the key has the required scopes, the hostname matches, and the rate limit allows it.
- Each key's last-used time is shown in Settings → Developer.
- Never put a key in a browser, mobile app, or any other client-side code. Anyone who can load the code can read the key. Call the API from your server.
- Do not commit keys to source control. Load them from environment variables or a secret manager.
- Use one key per integration so you can revoke one without breaking the others.
- Prefer short expiries and rotate keys before they expire.
- Create a new key with the same scopes.
- Deploy it to your integration.
- Confirm traffic has moved: call
GET /v1/mewith the new key and check the old key's last-used time. - Revoke the old key in Settings → Developer.