Overview
Entities module for managing app data. This module provides dynamic access to all entities in the app. Each entity gets a handler with full CRUD operations and additional utility methods. Entities are accessed dynamically using the pattern:base44.entities.EntityName.method()
This module is available to use with a client in all authentication modes:
- Anonymous or User authentication (
base44.entities): Access is scoped to the current user’s permissions. Anonymous users can only access public entities, while authenticated users can access entities they have permission to view or modify. - Service role authentication (
base44.asServiceRole.entities): Operations bypass entity access rules and field-level security entirely. Can read and write any record in any entity.
Entity Handlers
An entity handler is the object you get when you access an entity throughbase44.entities.EntityName. Every entity in your app automatically gets a handler with CRUD methods for managing records.
For example, base44.entities.Task is an entity handler for Task records, and base44.entities.User is an entity handler for User records. Each handler provides methods like list(), create(), update(), and delete().
You don’t need to instantiate or import entity handlers. They’re automatically available for every entity you create in your app.
Built-in User Entity
Every app includes a built-inUser entity that stores user account information. This entity has special security rules that can’t be changed.
Regular users can only read and update their own user record. With service role authentication, you can read, update, and delete any user. You can’t create users using the entities module. Instead, use the functions of the auth module to invite or register new users.
Generated Types
If you’re working in a TypeScript project, you can generate types from your entity schemas to get autocomplete and type checking on all entity methods. See the Dynamic Types guide to get started.Examples
Entity Handler Methods
get()
get(Gets a single record by ID. Retrieves a specific record using its unique identifier.id):Promise<T>
Parameters
string
required
The unique identifier of the record.
Returns
Promise<T>
Promise resolving to the record.
Example
Entity handler providing CRUD operations for a specific entity type. Each entity in the app gets a handler with these methods for managing data.
list()
Thelist() method has three forms:
- Records (cursor): Returns one cursor page of records. Use this for loops, or any time you want pagination that’s unaffected by records added or deleted mid-walk.
- Distinct values (cursor): Returns one cursor page of a single field’s distinct values, always in ascending order. Use it to list the unique values of a field, for example to populate filter options or autocomplete.
- Records (skip): Returns an array of records. Kept for existing code. Prefer a cursor for pagination instead.
list<Lists one cursor page of records, sorted and optionally field-selected. PassK extends keyof T>(options):Promise<EntityPage<Pick<T,K>>>
cursor from the previous page’s next_cursor to keep paging, or omit it
for the first page. Records added or deleted between pages never shift the boundary.
Parameters
EntityListOptions<T, K>
required
Paging options.
Properties
Properties
SortField<T>
A
SortField<T> specifying sort order, such as '-priority' for descending. Defaults to '-created_date'.number
Maximum number of records per page, up to 5,000. Defaults to 100.
string | null
The
next_cursor from the previous page. Omit or pass null for the first page.The token carries this walk’s parameters, so a later page needs only
cursor and limit. Passing different parameters with a cursor is an error.(keyof T)[]
Array of field names to include in each record. Defaults to all fields.
Returns
EntityPage
One page of items, with a cursor to continue.
Properties
Properties
T[]
required
The page’s items. Without
distinct, these are records in the requested sort order. With distinct, these are that field’s distinct values instead of records, in ascending order.string | null
required
A cursor for the next page, or
null on the last page. Pass it as cursor to keep paging.boolean
required
Whether records remain after this page.
Examples
list<Lists one cursor page of a single field’s distinct values, instead of records.K extends keyof T>(options):Promise<EntityPage<T[K]>>
Parameters
EntityDistinctOptions<T, K>
required
Paging options naming the field to read.
Properties
Properties
K
required
Field whose distinct values to return, in ascending order. For an array field like
tags, this returns the distinct individual tags used across records, not the distinct arrays.number
Maximum number of values per page, up to 1,000. Defaults to 100.
string | null
The
next_cursor from the previous page. Omit or pass null for the first page. The token carries this lookup’s parameters.Returns
EntityPage
One page of items, with a cursor to continue.
Properties
Properties
T[]
required
The page’s items. Without
distinct, these are records in the requested sort order. With distinct, these are that field’s distinct values instead of records, in ascending order.string | null
required
A cursor for the next page, or
null on the last page. Pass it as cursor to keep paging.boolean
required
Whether records remain after this page.
Examples
list<Lists records as an array, usingK extends keyof T>(
sort?,
limit?,
skip?,
fields?
):Promise<Pick<T,K>[]>
skip for pagination.
Kept for existing code. Prefer a cursor for pagination instead.
Parameters
Properties
Properties
SortField<T>
A
SortField<T> specifying sort order, such as '-priority' for descending. Defaults to '-created_date'.number
Maximum number of results to return. Defaults to
5000.number
Number of results to skip for pagination. Defaults to
0. Prefer a cursor for loops instead.(keyof T)[]
Array of field names to include in the response. Defaults to all fields.
Returns
Promise<Pick<T, K>[]>
Promise resolving to an array of records with selected fields.
Examples
filter()
Thefilter() method has three forms. The query is always the first argument.
- Records (cursor): Returns one cursor page of matching records. Use this for loops, or any time you want pagination that’s unaffected by records added or deleted mid-walk.
- Distinct values (cursor): Returns one cursor page of a single field’s distinct values among matching records, always in ascending order. Use it to list the unique values of a field among matching records, for example to populate filter options or autocomplete.
- Records (skip): Returns an array of matching records. Kept for existing code. Prefer a cursor for pagination instead.
filter<Filters and returns one cursor page of matching records, sorted and optionally field-selected. PassK extends keyof T>(query,options):Promise<EntityPage<Pick<T,K>>>
cursor from the previous page’s next_cursor to keep paging, or omit it
for the first page. Records added or deleted between pages never shift the boundary.
Parameters
Properties
Properties
EntityFilterQuery<T>
required
Query matching
EntityFilterQuery. Field names are
case-sensitive, and records matching every field are returned.EntityListOptions<T, K>
required
Paging options.
Properties
Properties
SortField<T>
A
SortField<T> specifying sort order, such as '-priority' for descending. Defaults to '-created_date'.number
Maximum number of records per page, up to 5,000. Defaults to 100.
string | null
The
next_cursor from the previous page. Omit or pass null for the first page.The token carries this walk’s parameters, so a later page needs only
cursor and limit. Passing different parameters with a cursor is an error.(keyof T)[]
Array of field names to include in each record. Defaults to all fields.
Returns
EntityPage
One page of items, with a cursor to continue.
Properties
Properties
T[]
required
The page’s items. Without
distinct, these are records in the requested sort order. With distinct, these are that field’s distinct values instead of records, in ascending order.string | null
required
A cursor for the next page, or
null on the last page. Pass it as cursor to keep paging.boolean
required
Whether records remain after this page.
Examples
filter<Filters and returns one cursor page of a single field’s distinct values among matching records.K extends keyof T>(query,options):Promise<EntityPage<T[K]>>
Parameters
Properties
Properties
EntityFilterQuery<T>
required
Query matching
EntityFilterQuery. Field names are
case-sensitive, and records matching every field are returned.EntityDistinctOptions<T, K>
required
Paging options naming the field to read.
Properties
Properties
K
required
Field whose distinct values to return, in ascending order. For an array field like
tags, this returns the distinct individual tags used across records, not the distinct arrays.number
Maximum number of values per page, up to 1,000. Defaults to 100.
string | null
The
next_cursor from the previous page. Omit or pass null for the first page. The token carries this lookup’s parameters.Returns
EntityPage
One page of items, with a cursor to continue.
Properties
Properties
T[]
required
The page’s items. Without
distinct, these are records in the requested sort order. With distinct, these are that field’s distinct values instead of records, in ascending order.string | null
required
A cursor for the next page, or
null on the last page. Pass it as cursor to keep paging.boolean
required
Whether records remain after this page.
Examples
filter<Filters records as an array, usingK extends keyof T>(
query,
sort?,
limit?,
skip?,
fields?
):Promise<Pick<T,K>[]>
skip for pagination.
Kept for existing code. Prefer a cursor for pagination instead.
Parameters
Properties
Properties
EntityFilterQuery<T>
required
Query matching
EntityFilterQuery. Field names are
case-sensitive, and records matching every field are returned.SortField<T>
A
SortField<T> specifying sort order, such as '-priority' for descending. Defaults to '-created_date'.number
Maximum number of results to return. Defaults to
5000.number
Number of results to skip for pagination. Defaults to
0. Prefer a cursor for loops instead.(keyof T)[]
Array of field names to include in the response. Defaults to all fields.
Returns
Promise<Pick<T, K>[]>
Promise resolving to an array of filtered records with selected fields.
Examples
count()
count(Counts the records that match a query. Returns the number of records the current user can read, without fetching them. Use it for totals, badges and “page N of M”.query?):Promise<number>
Parameters
EntityFilterQuery<T>
Query matching
EntityFilterQuery. Defaults to all records.Returns
Promise<number>
Promise resolving to the number of matching records.
Examples
aggregate()
aggregate(Computes counts, sums, averages, minimums, maximums or distinct counts, grouped by fields. Use it for dashboards, leaderboards and reports instead of loading every record and adding up in the browser. The server groups the records you can read and returns one row per group, up to 1,000 rows.spec):Promise<EntityAggregateResult>
Parameters
EntityAggregateSpec<T>
required
What to group by and what to compute.
Properties
Properties
EntityFilterQuery<T>
Filter applied before grouping, matching
EntityFilterQuery. Defaults to all records.(keyof T & string) | (keyof T & string)[]
Field, or up to four fields, to group by. Omit to get one total row.
EntityDateBucket<T>
Group by a time bucket of a date field.
boolean
Whether to include the number of records per group as
count. Defaults to true.(keyof T & string) | (keyof T & string)[]
Field, or fields, to sum. Each appears in the rows as
sum_<field>.(keyof T & string) | (keyof T & string)[]
Field, or fields, to average. Each appears in the rows as
avg_<field>.(keyof T & string) | (keyof T & string)[]
Field, or fields, to take the minimum of. Each appears in the rows as
min_<field>.(keyof T & string) | (keyof T & string)[]
Field, or fields, to take the maximum of. Each appears in the rows as
max_<field>.keyof T & string
Field whose distinct values to count per group, returned as
count_distinct_<field>. Unlike distinct on list()/filter(), an array field here counts each whole array as one value, not its individual elements.Record<string, any>
Filter applied to the computed fields after grouping, not to raw or
groupBy fields. Supports $eq, $ne, $gt, $gte, $lt, $lte, $in, and $nin. With more than one key, a row is kept only when every key’s condition holds. For example, grouped by external_id, having: { count: { $gt: 1 } } keeps only the external ids that appear in more than one record.string
Computed or group field to sort the rows by, with a
- prefix for descending. For example '-count'.number
Maximum number of rows, up to 1,000. Defaults to 1,000.
Returns
EntityAggregateResult
Rows returned by aggregate().
Properties
Properties
Examples
create()
create(Creates a new record. Creates a new record with the provided data.data):Promise<T>
Parameters
Partial<T>
required
Object containing the record data.
Returns
Promise<T>
Promise resolving to the created record.
Example
bulkCreate()
bulkCreate(Creates multiple records in a single request. Efficiently creates multiple records at once. This is faster than creating them individually.data):Promise<T[]>
Parameters
Partial<T>[]
required
Array of record data objects.
Returns
Promise<T[]>
Promise resolving to an array of created records.
Example
importEntities()
importEntities(Imports records from a file. Imports records from a file, typically CSV or similar format. The file format should match your entity structure. Requires a browser environment and can’t be used in the backend.file):Promise<ImportResult<T>>
Parameters
File
required
File object to import.
Returns
ImportResult<T>
Result returned when importing entities from a file.
Properties
Properties
Example
upsert()
upsert(Creates or updates records by a key you define, instead of byrecords,options):Promise<EntityUpsertResult<T>>
id.
Use this whenever records have a natural key, such as an ID from another system or a
one-per-user record keyed by user_id, so you don’t have to look up each record first
to decide between create and update. Name the field, or fields, that identify a record,
and the server updates the records whose key already exists and creates the rest, in
one call.
You can upsert up to 500 records per request. When two records in one call share a
key, the last one wins. Updates merge the given fields into the existing record, like
update().
Parameters
Properties
Properties
Partial<T>[]
required
Array of record data objects. Each must carry a value, not an object or array, for every
field named in
options.key, to find or create by. Other fields are optional, and only
the ones you include are merged into a matched record, like update().EntityUpsertOptions<T>
required
The key field or fields.
Properties
Properties
(keyof T & string) | (keyof T & string)[]
required
Field, or fields, that identify a record. A record whose key values match an existing record updates it, and any other record is created.
Returns
EntityUpsertResult
Result returned by upsert().
Properties
Properties
Examples
update()
update(Updates an existing record. Updates a record by ID with the provided data. Only the fields included in the data object will be updated. To update a single record by ID, use this method. To apply the same update to many records matching a query, useid,data):Promise<T>
updateMany().
To update multiple specific records with different data each, use
bulkUpdate().
Parameters
Properties
Properties
Returns
Promise<T>
Promise resolving to the updated record.
Examples
updateMany()
updateMany(Applies the same update to all records that match a query. Use this when you need to make the same change across all records that match specific criteria. For example, you could set every completed order to “archived”, or increment a counter on all active users. Results are batched in groups of up to 500. Whenquery,data):Promise<UpdateManyResult>
has_more is true
in the response, call updateMany again with the same query to update
the next batch. Make sure the query excludes already-updated records
so you don’t re-process the same entities on each iteration. For
example, filter by status: 'pending' when setting status to 'processed'.
To update a single record by ID, use update() instead. To update
multiple specific records with different data each, use bulkUpdate().
Parameters
Properties
Properties
Partial<T>
required
Query matching
EntityFilterQuery, selecting which records to update.Record<string, Record<string, any>>
required
Update operation object containing one or more
MongoDB update operators.
Each field may only appear in one operator per call.
Supported update operators include
$set, $rename, $unset, $inc, $mul, $min, $max,
$currentDate, $addToSet, $push, and $pull.Returns
UpdateManyResult
Result returned when updating multiple entities using a query.
Properties
Properties
Examples
bulkUpdate()
bulkUpdate(Updates the specified records in a single request, each with its own data. Use this when you already know which records to update and each one needs different field values. For example, you could update the status and amount on three separate invoices in one call. You can update up to 500 records per request. To apply the same update to all records matching a query, usedata):Promise<T[]>
updateMany(). To update a single record by ID, use
update().
Parameters
(Partial<T> & { id: string })[]
required
Array of objects to update. Each object must contain an
id field identifying which record to update and any fields to change.Returns
Promise<T[]>
Promise resolving to an array of the updated records.
Examples
delete()
delete(Deletes a single record by ID. Permanently removes a record from the database.id):Promise<DeleteResult>
Parameters
string
required
The unique identifier of the record to delete.
Returns
DeleteResult
Result returned when deleting a single entity.
Properties
Properties
boolean
required
Whether the deletion was successful.
Example
deleteMany()
deleteMany(Deletes multiple records matching a query. Permanently removes all records that match the provided query.query):Promise<DeleteManyResult>
Parameters
Partial<T>
required
Query matching
EntityFilterQuery. Every matching record is deleted.Returns
DeleteManyResult
Result returned when deleting multiple entities.
Properties
Properties
Example
subscribe()
subscribe(Subscribes to realtime updates for all records of this entity type. Establishes a WebSocket connection to receive instant updates when any record is created, updated, or deleted. Returns an unsubscribe function to clean up the connection.callback): () =>void
Parameters
RealtimeCallback<T>
required
Callback function called when an entity changes. The callback receives an event object with the following properties:
type: The type of change that occurred -'create','update', or'delete'.data: The entity data after the change.id: The unique identifier of the affected entity.timestamp: ISO 8601 timestamp of when the event occurred.
Returns
Unsubscribe function to stop receiving updates.Example
Type Definitions
EntityRecord
EntityRecord = { [K in keyof EntityTypeRegistry]: EntityTypeRegistry[K] & ServerEntityFields }
Combines the EntityTypeRegistry schemas with server fields like id, created_date, and updated_date to give the complete record type for each entity. Use this when you need to type variables holding entity data.
Example
EntityTypeRegistry
Registry mapping entity names to their TypeScript types. The
types generate command fills this registry, then EntityRecord adds server fields.
SortField
SortField<Sort field type for entity queries. Accepts any field name from the entity type with an optional prefix:T> =keyof T|`+${keyof T}`|`-${keyof T}`
'+'prefix or no prefix: ascending sort'-'prefix: descending sort
Example
EntityFilterQuery
EntityFilterQuery<Query object accepted byT> ={ [K in keyof T]?: EntityFilterValue<T[K]> }&object
filter(),
count(), deleteMany(),
updateMany(), and the query field of
EntityAggregateSpec.
Field keys are typed from the entity schema. Each field can use an exact value, null,
an array shorthand for matching any of the listed values, or a field-level operator
object. Root-level $and, $or, and $nor combine nested filter queries.
Operator values are typed from the field they filter where possible. For example,
numeric fields accept numeric comparison values, string fields accept $regex, and
array fields accept $all and $size.
Type Declarations
$and?
optional$and:EntityFilterQuery<T>[]
$or?
optional$or:EntityFilterQuery<T>[]
$nor?
optional$nor:EntityFilterQuery<T>[]