Record types and fields API
List and create record types and menu groups, add fields with rules, and set auto-numbering, formulas and descriptions.
Record types describe what a workspace stores (an invoice, a customer, a work order). Fields describe what each record of a type holds. These routes read and change that structure, the same things you edit in the product's record type and field settings.
Endpoints
| Method | Path | Permission | What it does |
|---|---|---|---|
GET |
/orgs/{orgId}/types |
types:read |
List record types |
POST |
/orgs/{orgId}/types |
types:create |
Create a record type |
PATCH |
/orgs/{orgId}/types/{typeKey} |
types:update |
Change label, icon, app, layout hints or description |
DELETE |
/orgs/{orgId}/types/{typeKey} |
types:delete |
Delete a custom record type |
GET |
/orgs/{orgId}/modules |
any member | List menu groups |
POST |
/orgs/{orgId}/modules |
org:update |
Create or update a menu group |
DELETE |
/orgs/{orgId}/modules/{slug} |
org:update |
Delete a menu group |
GET |
/orgs/{orgId}/fields?entity_type={typeKey} |
fields:read |
List a type's fields |
POST |
/orgs/{orgId}/fields |
fields:create |
Add a field |
DELETE |
/orgs/{orgId}/fields/{fieldId} |
fields:delete |
Delete a custom field |
PUT |
/orgs/{orgId}/fields/{fieldId}/autogen |
fields:create |
Turn on auto-numbering |
DELETE |
/orgs/{orgId}/fields/{fieldId}/autogen |
fields:create |
Turn off auto-numbering |
PUT |
/orgs/{orgId}/fields/{fieldId}/formula |
fields:create |
Make a field computed |
DELETE |
/orgs/{orgId}/fields/{fieldId}/formula |
fields:create |
Make it an ordinary field again |
PUT |
/orgs/{orgId}/fields/{fieldId}/description |
fields:create |
Set the field description |
PUT |
/orgs/{orgId}/fields/{fieldId}/ref-type |
fields:create |
Point a reference field at another type |
The field permissions are checked against the record type: you need fields:create on that type (resource = type key).
Record types
The type object
{
"id": "0190f0aa-…",
"key": "work_orders",
"label": "Work order",
"icon": "ledger",
"app": "operations",
"ui": { "lines": { "type": "work_order_lines", "ref": "work_order" } },
"description": "Jobs raised for the workshop",
"record_count": 128,
"created_at": "2026-10-01T08:00:00Z"
}
Built-in types (such as invoices, payments, accounts, locations) have "system": true and no id. They cannot be deleted.
POST /orgs/{orgId}/types
| Field | Type | Required | Notes |
|---|---|---|---|
key |
string | Yes | Lowercase letters, digits and underscores, starting with a letter, 2 to 32 characters. Cannot be changed later. Must be unused |
label |
string | Yes | 1 to 100 characters |
icon |
string | No | An icon name, up to 32 characters |
app |
string | No | The menu group (module slug) the type is filed under |
ui |
string | No | Layout hints as a JSON string, up to 2048 characters: {"child":true} for a type that only exists under another, or {"lines":{"type":"child_type_key","ref":"ref_field_key"}} for line items |
curl -s -X POST https://axisiq.co/api/v1/orgs/$ORG/types \
-H "Authorization: Bearer $AXIS_KEY" -H "Content-Type: application/json" \
-d '{"key": "work_orders", "label": "Work order", "app": "operations"}'
Response 201 with the type object. Errors: 400 VALIDATION_ERROR (key or label rule), 409 KEY_TAKEN, 402 LIMIT_EXCEEDED.
PATCH /orgs/{orgId}/types/{typeKey}
Send only what changes: label, icon, app, ui, description. Response 200 with the type object.
DELETE /orgs/{orgId}/types/{typeKey}
Returns 204 No Content. Built-in types answer 403 FORBIDDEN.
Important: Deleting a type removes its records and fields from the workspace. This cannot be undone.
Menu groups (modules)
A module is a group in the main menu that record types are filed under.
{ "slug": "operations", "name": "Operations", "glyph": "ledger", "category": "Operations", "position": 10 }
POST /modules creates or updates by slug (required, up to 32 characters; name required, up to 100; glyph, category up to 32; position a number). DELETE /modules/{slug} returns 204.
Fields
The field object
{
"id": "0190f0bb-…",
"entity_type": "invoices",
"key": "po_number",
"label": "PO number",
"type": "string",
"required": false,
"unique": true,
"immutable": false,
"autogen": "",
"description": "Customer purchase order",
"rules": { "max_len": 40 },
"created_at": "2026-10-01T08:05:00Z"
}
system: true marks fields built into a built-in type. They cannot be changed or deleted.
Field types
string, text, number, bool, date, datetime, currency, select, multiselect, email, url, file, ref, refs. How each is sent and read is in Records.
POST /orgs/{orgId}/fields
| Field | Type | Required | Notes |
|---|---|---|---|
entity_type |
string | Yes | The record type key. Must exist |
key |
string | Yes | Lowercase letters, digits and underscores, starting with a letter, 2 to 64 characters. Unique within the type. Some names, such as id and created_at, are reserved |
label |
string | Yes | 1 to 100 characters |
type |
string | Yes | One of the types above |
required |
boolean | No | The record cannot be saved or updated without it |
unique |
boolean | No | No two records may hold the same value |
immutable |
boolean | No | Can be set when the record is created but never changed afterwards |
rules |
object | No | See below |
description |
string | No | Up to 255 characters |
rules
| Key | Applies to | Meaning |
|---|---|---|
min_len, max_len |
text fields | Length bounds |
pattern |
string |
A regular expression the value must match |
min, max |
number, currency |
Range of the amount |
options |
select, multiselect |
The allowed values. At least one is required |
unit |
currency |
An ISO 4217 code that fixes the field to one currency |
ref_type |
ref, refs |
The record type key the reference points at. Required |
default |
any | A value applied when a record is created without one. It must pass the field's own rules |
formula |
any | Makes the field computed. Set through the formula route instead |
curl -s -X POST https://axisiq.co/api/v1/orgs/$ORG/fields \
-H "Authorization: Bearer $AXIS_KEY" -H "Content-Type: application/json" \
-d '{"entity_type":"invoices","key":"channel","label":"Channel","type":"select","rules":{"options":["web","store","phone"],"default":"web"}}'
Response 201 with the field object. Errors: 400 VALIDATION_ERROR, 403 FORBIDDEN, 409 KEY_TAKEN.
GET /orgs/{orgId}/fields
Pass entity_type (required; permission fields:read on that type) to list one type's fields; the response is an array of field objects, built-in fields included.
DELETE /orgs/{orgId}/fields/{fieldId}
Returns 204 No Content. A field that a computed field's formula reads is refused (400 VALIDATION_ERROR) until that formula is removed. Built-in fields answer 404 NOT_FOUND.
Important: Deleting a field discards the values stored in it for every record.
PUT /orgs/{orgId}/fields/{fieldId}/autogen
Fill a string field automatically when a record is created without a value. A value you supply always wins. Other field types and computed fields are refused with 400 VALIDATION_ERROR.
| Field | Type | Required | Notes |
|---|---|---|---|
pattern |
string | Yes | Text with tokens. Exactly one {seq} token is required |
next |
number | No | When above 0, the next number issued is at least this, for continuing an existing numbering |
Tokens:
| Token | Meaning |
|---|---|
{seq} |
Running number |
{seq:4} |
Running number padded with zeros to 4 digits (1 to 10) |
{seq:4:yearly} |
As above, restarting each daily, monthly or yearly period. A restarting pattern must include the period's date tokens |
{yyyy} {yy} {mm} {dd} |
Creation date (UTC) |
Example: INV/{yyyy}/{seq:4:yearly} produces INV/2026/0001. Patterns are up to 100 characters. Response 200 with the field object. DELETE on the same path turns it off (204).
PUT /orgs/{orgId}/fields/{fieldId}/formula
Make a custom field computed from other fields of the same record.
{ "formula": "price - cost" }
Fields are referenced by key. IF(status="paid", total, 0) style expressions are supported, using the same formula language as Sheets. A computed field is recomputed by the platform on every write, cannot be written to directly, and holds an empty value when the formula cannot be evaluated. Existing records are recalculated shortly after you save. DELETE on the same path makes it an ordinary field (204). Response 200 with the field object; 400 VALIDATION_ERROR for a bad formula.
PUT /orgs/{orgId}/fields/{fieldId}/description
{ "description": "Customer purchase order number" }
An empty string clears it. Maximum 255 characters. Response 200 with the field object.
PUT /orgs/{orgId}/fields/{fieldId}/ref-type
{ "ref_type": "customers" }
Re-points a ref or refs field at another existing record type. Ids already stored are not changed. Response 200 with the field object.