Developers

A REST API that reads like any other.

Server-to-server, bearer-authenticated, scoped to a tenant with one header. If you’ve used a REST API, you already know how this works.

Authentication

Three headers, from your backend.

Fluidlee is a server-to-server API. Your backend holds the key and calls us on behalf of the logged-in user, always from your server.

HeaderWhat it does
Authorization: Bearer <key> Required Your project API key (prefix flk_). Identifies the project; the entity comes from the URL, not the key.
X-Tenant-ID: <uuid> Required The tenant this request is scoped to. Every row read or written is confined to it.
X-Actor-ID: <string> Optional An opaque id for the end user acting. Recorded in the audit log purely as a label.

Endpoints

Five per entity.

The project comes from your API key; the entity comes from the URL. For an entity named patient, replace :entity with patient.

MethodPathDoes
GET /:entity List records, filtered, sorted, paginated
POST /:entity Create a record
GET /:entity/:id Fetch one record by id
PATCH /:entity/:id Partial update
DELETE /:entity/:id Soft-delete (sets deleted_at)

Listing

Filter, sort, paginate.

GETlist with filters
GET https://api.fluidlee.com/appointment?status=confirmed&scheduled_at[gte]=2026-07-01&orderBy=scheduled_at&orderDir=asc&page=1&pageSize=25
Authorization: Bearer flk_live_a8f3...
X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000
200 OKresponse
{
  "data": [
    { "id": "3f2c...", "status": "confirmed", "scheduled_at": "2026-07-03T09:00:00Z" }
  ],
  "total": 128,
  "page": 1,
  "pageSize": 25
}
Filter operators
SyntaxMeans
?field=valueExact match
?field[eq]=Equal to
?field[gt]=Greater than
?field[gte]=Greater than or equal
?field[lt]=Less than
?field[lte]=Less than or equal
?field[like]=Pattern match (SQL LIKE, % wildcard)
?field[isnull]=1Field is null or absent
?field[notnull]=1Field is present
Pagination & sorting
ParamMeans
pagePage number (1-based). Default 1.
pageSizeRecords per page. Default 50, capped server-side.
orderByField to sort by. Default created_at.
orderDirasc or desc. Default desc.

Writing

Create a record.

Send the fields flat in the body. The platform validates types, checks foreign keys against the same tenant, runs before_create rules, and returns the stored record, computed fields included.

POST/patient
curl https://api.fluidlee.com/patient \
  -H "Authorization: Bearer flk_live_a8f3..." \
  -H "X-Tenant-ID: 550e8400-e29b-41d4-a716-446655440000" \
  -H "X-Actor-ID: usr_2f10" \
  -H "Content-Type: application/json" \
  -d '{ "first_name": "Jane", "mrn": "MRN-4471", "clinician_id": "9b1c..." }'
201response
# 201 Created: computed fields included, FK validated against this tenant
{
  "data": {
    "id": "7d90c4b2-...",
    "first_name": "Jane",
    "mrn": "MRN-4471",
    "created_at": "2026-07-24T14:22:11Z"
  }
}
JSreading one record from your backend
// Always from your backend. The key stays server-side.
const res = await fetch(`https://api.fluidlee.com/invoice/${id}`, {
  headers: {
    'Authorization': `Bearer ${process.env.FLUIDLEE_API_KEY}`,
    'X-Tenant-ID': tenantId,
  },
});
const { data } = await res.json();

Errors

What can come back.

Every error is JSON with a stable code you can branch on. These are the ones you’ll actually meet.

StatusCodeMeaning
400 INVALID_ENTITY / INVALID_ID The entity name or record id in the URL is malformed.
404 ENTITY_NOT_FOUND / NOT_FOUND No such entity in the project, or no such record for this tenant.
422 VALIDATION_ERROR A field failed type, required, or foreign-key validation. The body lists each field error.
422 BLOCKED_BY_RULE A before_* rule blocked the mutation. The rule’s message is returned.
403 FEATURE_NOT_IN_TIER The request used a capability the project’s plan doesn’t include.
429 RATE_LIMIT_EXCEEDED Too many requests per minute for the tier. Slow down and retry.
429 REQUEST_QUOTA_EXCEEDED The project’s request allowance for the billing period is spent. The response says when it resets.
507 STORAGE_QUOTA_EXCEEDED Storage is full. Writes are blocked; reads keep working.
503 PROJECT_PAUSED A Free project was paused after 7 idle days. Reactivate it from the dashboard.
OpenAPI

A spec that matches your schema

Each project publishes an OpenAPI document generated from its current schema, so your client code, types and tooling stay in step with what the API accepts. Find it in the dashboard under API reference.

Ready to make the first call?

Request access, define a schema, and your project’s API is live before you finish your coffee.