Records API
Create, read, search, filter, sort, update and delete records, import and export CSV, and read the change history.
Records are the rows of your workspace: invoices, customers, products, or any record type you create. This API creates, reads, searches, updates and deletes them, imports and exports CSV, and reads their change history.
Every record type works the same way, so one set of routes covers all of them. {typeKey} is the key of the record type, such as invoices. List your types with GET /types.
Endpoints
| Method | Path | Permission | What it does |
|---|---|---|---|
POST |
/orgs/{orgId}/records/{typeKey} |
records:create |
Create a record |
GET |
/orgs/{orgId}/records/{typeKey} |
records:read |
List records, or search, filter and sort them |
GET |
/orgs/{orgId}/records/{typeKey}/{recordId} |
records:read |
Get one record |
PUT |
/orgs/{orgId}/records/{typeKey}/{recordId}/values |
records:update |
Change field values |
GET |
/orgs/{orgId}/records/{typeKey}/{recordId}/values |
records:read |
Read just the values |
DELETE |
/orgs/{orgId}/records/{typeKey}/{recordId} |
records:delete |
Delete a record |
GET |
/orgs/{orgId}/records/{typeKey}/export |
records:export |
Download CSV |
POST |
/orgs/{orgId}/records/{typeKey}/import |
records:import |
Create records from CSV |
GET |
/orgs/{orgId}/audit |
audit:read |
Change history |
Permissions can be limited to a record type (the resource is the type key) and can carry conditions such as "only records you own". A record that fails the condition reads as not found. See Policy format.
The record object
{
"id": "0190f0aa-7c1e-7a3b-9d52-4f0e6c1b2a10",
"object_type": "invoices",
"created_by": "0190f0a0-3b44-7d10-8a21-90c4e7f01d55",
"created_at": "2026-10-04T09:30:00Z",
"updated_at": "2026-10-04T09:30:00Z",
"values": {
"number": "INV-1001",
"status": "open",
"issue_date": "2026-10-04",
"amount": { "amount": 12500, "code": "INR" }
}
}
values is keyed by field key. Fields your role may not read are left out.
Value formats
| Field type | Send | Read back |
|---|---|---|
string, text, email, url |
string. Email must be a valid address; URL must be absolute http or https |
string |
number |
number or numeric string, up to 14 digits before and 6 after the decimal point | number |
currency |
{"amount": 12500, "code": "INR"}, or a bare number |
{"amount": …, "code": "INR"} |
bool |
true or false (the strings "true"/"false" are accepted) |
boolean |
date |
"2026-10-04" |
string |
datetime |
RFC 3339, such as "2026-10-04T09:30:00Z" |
RFC 3339 in UTC |
select |
one of the field's options | string |
multiselect |
array of options, no duplicates, at most 100 | array |
ref |
the UUID of another record | string |
refs |
array of record UUIDs, at most 100 | array |
file |
a Drive key (text) | string |
Text limits: string up to 500 characters, text up to 100,000. Sending null clears a field unless it is required. Computed fields (formula fields) are read-only: any value you send for them is ignored.
POST /orgs/{orgId}/records/{typeKey}
Create a record. Permission: records:create.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
values |
object | No | Field values by key. Required fields must be present unless they have a default or an auto-numbering pattern. An empty body creates an empty record if no field is required |
curl -s -X POST https://axisiq.co/api/v1/orgs/$ORG/records/invoices \
-H "Authorization: Bearer $AXIS_KEY" -H "Content-Type: application/json" \
-d '{"values": {"number": "INV-1002", "status": "open", "amount": {"amount": "980.50", "code": "INR"}}}'
Response 201 with the record object.
Errors
| Status | Code | When |
|---|---|---|
| 400 | VALIDATION_ERROR |
A value breaks its field's type or rules, or a required field is missing |
| 403 | FORBIDDEN |
The role lacks records:create for this type, or a condition fails on the new values |
| 404 | NOT_FOUND |
No such record type |
| 402 | LIMIT_EXCEEDED |
A free-plan cap was reached |
| 409 | DUPLICATE_VALUE |
A unique field already holds the value |
GET /orgs/{orgId}/records/{typeKey}
List records. Newest first. Permission: records:read.
There are two modes. The mode is chosen by the parameters you send.
Plain listing (cursor paging)
| Parameter | Notes |
|---|---|
limit |
1 to 200, default 50 |
cursor |
The next_cursor from the previous page |
ref_field and ref_id |
Together: only records whose reference field ref_field points at the record ref_id. For example the lines of one order |
{
"data": {
"records": [ { "id": "0190f0aa-…", "object_type": "invoices", "values": { "…": "…" } } ],
"next_cursor": "0190f0a9-…"
}
}
When there are no more pages next_cursor is absent. Records your role may not read are skipped, so a page can hold fewer than limit items even when more exist; keep following next_cursor until it is absent.
Search mode (offset paging)
Use any of q, filter, sort, page or offset to search.
| Parameter | Notes |
|---|---|
q |
Text to find. Matches any text field (string or text type) that contains it |
filter |
A JSON array of conditions, URL-encoded. All conditions must match |
sort |
A field key, or created_at. Default is newest first |
dir |
asc or desc. Default desc |
limit |
1 to 200, default 50 |
page |
1-based page number |
offset |
Start position, instead of page |
{ "data": { "records": [ … ], "total": 137 } }
total counts only the records you may read.
Filter syntax
[
{ "field": "status", "op": "eq", "value": "open" },
{ "field": "amount", "op": "gte", "value": "10000" },
{ "field": "issue_date", "op": "lt", "value": "2026-10-01" }
]
value is always a string. The operators you can use depend on the field type:
| Field type | Operators |
|---|---|
string, text, select, email, url |
eq, ne, contains (the default when op is omitted) |
number, currency |
eq (default), ne, gt, gte, lt, lte. The value must be a number. Currency compares the amount |
date, datetime |
eq (default), ne, gt, gte, lt, lte. The value is YYYY-MM-DD or RFC 3339 |
bool |
eq, with "true" or "false" |
ref |
eq, with a record id |
refs, multiselect |
Not filterable or sortable |
Fields your role cannot read cannot be filtered on, sorted by, or matched by q. Doing so is a 400 VALIDATION_ERROR.
curl -s -G https://axisiq.co/api/v1/orgs/$ORG/records/invoices \
-H "Authorization: Bearer $AXIS_KEY" \
--data-urlencode 'q=acme' \
--data-urlencode 'filter=[{"field":"status","op":"eq","value":"open"}]' \
--data-urlencode 'sort=due_date' --data-urlencode 'dir=asc' \
--data-urlencode 'limit=100'
Errors: 400 VALIDATION_ERROR (bad limit, page, offset, or a filter that is not a JSON array of {field, op, value}), 403 FORBIDDEN (no way to read this type), 404 NOT_FOUND (no such type).
GET /orgs/{orgId}/records/{typeKey}/{recordId}
Get one record. Permission: records:read. Returns the record object. A record you may not read answers 404 NOT_FOUND.
PUT /orgs/{orgId}/records/{typeKey}/{recordId}/values
Change values on a record. Fields you do not send are left alone. Permission: records:update.
Request
{ "values": { "status": "paid", "amount": { "amount": "980.50", "code": "INR" } } }
| Field | Type | Required | Notes |
|---|---|---|---|
values |
object | Yes | Field values by key. null clears a field |
Response 204 No Content.
Fields marked write-once (immutable) cannot be changed after creation. A required field cannot be cleared.
Errors
| Status | Code | When |
|---|---|---|
| 400 | VALIDATION_ERROR |
Body is not {"values": {...}}, or a value breaks its rules |
| 403 | FORBIDDEN |
The role lacks records:update for this record |
| 404 | NOT_FOUND |
No such record, or you may not read it |
| 409 | DUPLICATE_VALUE |
A unique field already holds the value |
GET /orgs/{orgId}/records/{typeKey}/{recordId}/values
Returns {"data": {"values": { … }}} with the readable values.
DELETE /orgs/{orgId}/records/{typeKey}/{recordId}
Delete a record. Permission: records:delete. Returns 204 No Content.
Important: Deleting a record cannot be undone through the API. Other records that reference it keep the id and will show a missing reference.
GET /orgs/{orgId}/records/{typeKey}/export
Download the records of a type as CSV. Permission: records:export (and read access to the type).
- The first row is
id,created_at, then every field key. - Only records and fields your role may read are included.
- At most 10,000 records. If there were more, the response header
X-Export-Truncated: trueis set. - A cell that a spreadsheet could read as a formula (starting with
=,+,-,@) gets a leading'. Plain numbers and phone numbers are left as they are. Import removes the same'. - Currency cells read
12500 INR. List cells (refs,multiselect) are JSON arrays.
curl -s https://axisiq.co/api/v1/orgs/$ORG/records/invoices/export \
-H "Authorization: Bearer $AXIS_KEY" -o invoices.csv
POST /orgs/{orgId}/records/{typeKey}/import
Create records from a CSV. Permission: records:import.
Send either a multipart upload with a file field, or the CSV as the raw body with Content-Type: text/csv.
curl -s -X POST https://axisiq.co/api/v1/orgs/$ORG/records/invoices/import \
-H "Authorization: Bearer $AXIS_KEY" -H "Content-Type: text/csv" \
--data-binary @invoices.csv
- The first row is a header. Each column name must be a field key; other columns (including
idandcreated_at) are ignored. - Up to 500 data rows per request. More is a
400 VALIDATION_ERROR: split the file. - Empty cells are left unset, so defaults and auto-numbering still apply.
- Cell formats: booleans
true/false;refsandmultiselectas a JSON array or values separated by|; currency as12500 INRor a bare amount. - Rows are independent. A bad row is reported and skipped and the others are still created.
Response
{
"data": {
"created": 48,
"failed": 2,
"errors": [
{ "row": 7, "message": "amount: expected a number" },
{ "row": 19, "message": "a unique field already holds this value" }
]
}
}
row counts data rows starting at 1, not counting the header.
GET /orgs/{orgId}/audit
The change history of records. Permission: audit:read.
| Parameter | Notes |
|---|---|
object_type |
Record type key |
record_id |
One record |
actor |
A person's or service account's id |
action |
record.created, record.updated or record.deleted |
from, to |
RFC 3339 range |
limit |
Default 50, maximum 200 |
offset |
Start position |
{
"data": {
"entries": [
{
"id": "0190f0ab-…",
"actor_id": "0190f0a0-…",
"actor_type": "service",
"action": "record.updated",
"object_type": "invoices",
"record_id": "0190f0aa-…",
"before": { "status": "open" },
"after": { "status": "paid" },
"request_id": "9f2c41a0b7d3e655",
"created_at": "2026-10-04T10:02:11Z"
}
],
"total": 1
}
}
actor_type is user, service (an access key) or system (a change made by the platform itself with no signed-in caller).
Related
- Record types and fields
- Permissions reference
- In the product: Records