REST API for your data
Every table in your project database can be served as a REST endpoint. The API code is generated into your own repository, so it exports and deploys together with your app.
Turning the API on
API Functions needs a database, so it only works on projects created with PostgreSQL or MySQL. Without one the page says Enable a database first.
- In your project, open Settings → API Functions.
- Click Enable API.
- Wait. The button reads Enabling… while the platform writes the files, pushes the schema to your database, and wires up login — roughly 10–30 seconds.
Enabling is a real change to your project, not a platform-side switch: it adds files under lib/ and app/api/, plus one small table for API keys — all of it committed, so exporting the project takes the working API with it.
Each exposed table is served at /api/data/<model> — the model name, lowercased.
Choosing what is exposed
The Endpoints tab lists every table it found. Each card is a policy you control:
- Exposed — untick it and the endpoint returns 404, whatever the table holds.
- Owner column — pick the column that holds a user id. Signed-in users of your app then see and edit only their own rows. Leave it on (shared — no scoping) for tables everybody reads.
- Operations — tick any of
list,read,create,update,delete. - Field denylist (hidden) — tick a column to keep it out of every response, filter and sort.
Click Save on each card you change.
Columns whose names look like secrets — anything containing pass, secret, token, hash, apikey or credential — are stripped before any of that, on every model, including through a relation. You never have to remember to hide a password hash.
API keys
The API Keys tab issues keys for backends, scripts and third parties. They begin with pv_ and act as service-role callers: they bypass owner-column scoping.
- Click Create key, give it a Name, and set a Scope.
- Click Create. The key appears once, under Key created.
- Copy it before you close the dialog.
A key is shown exactly once. Lose it and no one can display it again — revoke it and create another.
A scope is * for full access, Model:* for every operation on one model, or Model:op for a single operation — for example Order:list. Anything not granted is denied. Use Scope on a row to narrow a key later, and Revoke to retire it: a revoked key is rejected immediately with 401 and cannot be restored.
Send a key as X-API-Key: pv_… or Authorization: Bearer pv_….
Querying your data
The list endpoint takes readable query parameters.
# newest first, second page of 50
curl "https://<slug>.poleved.app/api/data/order?sort=-createdAt&page=2&pageSize=50" \
-H "X-API-Key: pv_..."
# paid orders only, two columns, with the related author
curl "https://<slug>.poleved.app/api/data/order?filter[status][eq]=paid&select=id,total&expand=author" \
-H "X-API-Key: pv_..."
select=id,total— the columns you want back.filter[field][op]=value— repeatable, combined with AND. Operators:eq,ne,gt,gte,lt,lte,contains,startsWith,endsWith, andinfor a comma-separated list.sort=-createdAt,name— a leading-means descending.pageandpageSize— 20 per page by default, capped at 100.expand=author— pull in an allow-listed relation, up to 3 levels deep. The three rules above hold at every hop: a relation into a model that is not exposed, or that the key's scope does not cover, is refused, and the target's own hidden columns stay hidden. New projects allow every relation between two exposed models; a project enabled earlier has an empty list until you click Upgrade API code in Settings, or tick relations per model yourself.count=false— skip the total when you do not need it.
A list reply is { "data": [...], "pagination": { "page", "pageSize", "total", "totalPages" } }; a single row comes back as { "data": { ... } }. An unknown field or operator returns 400 instead of being ignored, so a typo surfaces immediately.
Access from your own app
Your app's own signed-in users can call the same endpoints with Authorization: Bearer <token>, using the token your login route issued. Where a model has an Owner column, they only see and change their own rows, and anything they create is stamped with their id.
If your project's scaffold ships the auth dependencies, enabling also generates POST /api/auth/login and POST /api/auth/register. Those, and other routes already in your project, are listed read-only under Feature endpoints.
A caller with neither a key nor a login is refused.
Keeping the generated code current
When newer generated helpers are available, the Endpoints tab shows a banner with an Upgrade API code button. It re-injects the latest files without recreating the API: your per-model policy, keys and custom endpoints are preserved, and a login route you customised is left alone. It is also what makes the rules above bind through expand: a project still on older helpers follows a relation without re-checking the target's exposure, the key's scope, or its hidden columns.
Limits & notes
- A database is required, and that choice is fixed at create time.
pageSizeis capped at 100; a larger value is clamped, not rejected.expandreaches at most 3 levels.- Enabling writes real files and one table into your project.
- Secret-looking columns are never returned, filtered on, sorted by, or written.
- A relation is reached by its foreign key, so for your app's signed-in users an owner column narrows the rows they asked for, not a relation followed from them. Untick Exposed, hide the column, or drop the relation to close that.
- Browsers on other origins are blocked until you allow them, and rate limiting is off until you turn it on — both live on the Security tab.
- Limits may change during alpha.