A Record Type is a sub-category inside an Object. It lets you classify records of the same Object into distinct buckets, each with its own subset of fields, views, and behaviors.
Examples:
- The
PeopleObject might have record typesLead,Vendor,Prospect. - The
DealsObject might have record typesNew Business,Renewal,Expansion.
Every Object has at least one record type. One of them is the default and is used when a record is created without specifying a record type.
Record Types belong to Objects, not Tables. Tables do not have categorical subdivisions.
| Field | Type | Notes |
|---|---|---|
id | number | Use as recordTypeId. |
name | string | Internal identifier within the Object. |
display_name | string | User-facing label. |
is_default | boolean | Exactly one record type per Object has this set to true. |
single_noun | string? | Singular noun used in UI copy (e.g."Lead" for the Leads type). |
emoji | string? | Icon-key string from the same allowlist Objects uses (e.g. "repeat", "star", "flag"). Not a Unicode emoji. |
icon_color | string? | Color name or hex. |
field_ids | number[]? | Subset of the Object's fields to show for records of this type. |
views | array? | Saved views scoped to this record type. |
- Field membership is record-type-scoped via
field_ids. A field on the Object can appear in some record types and not others. - Views can be scoped to a record type. Switching record type in the UI swaps the visible columns and the active view.
- Creating or updating a record can pin it to a specific record type. If you don't, it goes to the default.
| Verb | Path |
|---|---|
GET | /public/v1/objects/{name}/record-types |
POST | /public/v1/objects/{name}/record-types |
PATCH | /public/v1/objects/{name}/record-types/{recordTypeId} |
DELETE | /public/v1/objects/{name}/record-types/{recordTypeId} |
POST | /public/v1/objects/record-types/{recordTypeId}/views |
PATCH | /public/v1/objects/record-types/{recordTypeId}/views/{viewId} |
DELETE | /public/v1/objects/record-types/{recordTypeId}/views/{viewId} |
The default record type is protected: you cannot change its name or display_name, and you cannot delete it (both return 400). You can still update its other attributes (assigned columnIds, emoji, color) while it is default.
POST, PATCH, and DELETE require a USER API key with ADMIN or OWNER role; any other role gets a 403. GET is available to any user who can see the Object. Record types shape the account's CRM model, so they are deliberately not delegated through resource sharing the way Table schemas are.
Because record types are an Object-only feature, these endpoints reject Tables: passing a Table name returns 404 with a pointer to the /tables endpoints.
frontline object record-type list contacts
frontline object record-type create contacts --data '{"name":"vendor","displayName":"Vendor","fieldIds":[73],"emoji":"tag"}'
frontline object record-type update contacts <id> --data '{"displayName":"Vendor","fieldIds":[73,74]}'
frontline object record-type delete contacts <id>On create/update, columnIds, fieldIds, and field_ids are equivalent (assign fields to the record type). Aliases display_name, singleNoun, and singular_noun are also accepted.
Record-level security (RLS; some legacy references say "FLS") controls who can see and edit individual records within a record type. It is configured per record type, not per object.
When enabled, access is determined by virtual owner columns: User-relation fields on the record type (e.g. a Users column). Users listed in those fields become the virtual owners of the record and gain edit access according to workspace defaults.
This is separate from record sharing (per-record grants to specific users/teams) and from resource sharing (who can access the object schema itself). See the
sharingCLI skill for those.
When RLS is enabled for the first time on a record type:
- If workspace default is
FULL_ACCESS, it is set toNO_ACCESSautomatically. - Existing rows without
_grantsare backfilled to private so list/get/update enforcement applies immediately.
| RLS state | Non-owner USER |
|---|---|
| OFF | Normal record-type permissions; all rows visible |
| ON + workspace NO_ACCESS | Only own rows (manual/virtual owner) or explicit grants |
| ON + workspace FULL_ACCESS | Open rows readable/editable by the whole account |
Response fields: _recordAccess (record-type CRUD) vs _recordShareAccess (per-record RLS level).
Non-owners cannot get list/read access except via virtual-owner columns, per-record _grants, or an open workspace default. There is no separate ACL grant API on the record type.
| Verb | Path |
|---|---|
GET | /public/v1/objects/{name}/record-types/{recordTypeId}/security |
PATCH | /public/v1/objects/{name}/record-types/{recordTypeId}/security |
Both endpoints require a USER API key with ADMIN or OWNER role.
{
"ok": true,
"data": {
"enabled": false,
"workspace": "FULL_ACCESS",
"virtual_owner_column_ids": [42],
"virtual_owner_columns": [{ "id": 42, "name": "Users", "key": "users" }]
}
}All fields are optional (partial update). Unknown keys return 400.
{
"enabled": true,
"virtual_owner_column_ids": [42, 55],
"workspace": "READ_ONLY"
}Aliases virtualOwnerColumnIds, default_workspace_record_permission, and defaultWorkspaceRecordPermission are also accepted for their respective fields.
workspace values: FULL_ACCESS | READ_ONLY | NO_ACCESS — default access for new records when RLS is enabled.
virtual_owner_column_ids must reference User-relation fields that belong to the record type. Invalid column IDs return 400.
If no config has been saved yet, GET returns in-memory defaults (enabled: false, auto-detected Users column if present) without writing to the database. RLS enforcement only activates after an admin saves the config via PATCH.
frontline object record-type security get people 3
frontline object record-type security update people 3 --data '{"enabled":true,"virtual_owner_column_ids":[42],"workspace":"READ_ONLY"}'Get field IDs from frontline object get <object> or frontline object field list <object>.