/api/v1/object/data/{objectSlug}/{dataSlug}/logsList every change to one record, newest first.
List every change to one record, newest first.
Returns the record's whole change history in one response, with no
pagination. For long histories, use
GET /object/data/{objectSlug}/{dataSlug}/activity, which pages and
filters, when GET /object/features reports record_activity_tab: true.
Each entry names the action (created, updated, deleted, moved or
move_reversed), who made the change in performed_by, and each changed
field in changes, keyed by field slug in fieldName. field_name,
old_value and new_value repeat the first change. timestamp is
formatted for display in the credential owner's timezone.
Scope: read.<object slug>, for example read.contacts.
Errors:
400— no active object has that slug.400—Data with slug '9f2c4b7a1e03' not found: the record does not exist or the credential cannot see it.403— the credential lacksread.<object slug>.
Response 200:
{
"status": 200,
"message": "Logs retrieved successfully",
"data": [
{
"id": 58213,
"action": "updated",
"field_name": "Email",
"old_value": "sara@old.example.com",
"new_value": "sara@example.com",
"record_name": "Sara Ali",
"record_type": "record",
"object_slug": "contacts",
"data_slug": "9f2c4b7a1e03",
"performed_by": {
"id": 7,
"name": "Omar Hassan",
"profile_image": null,
"actor_type": "admin",
"on_behalf_of": null
},
"ip_address": "203.0.113.24",
"source_type": "manual",
"action_category": "field_change",
"changes": [
{
"fieldName": "email-k2v8x1qa",
"displayName": "Email",
"oldValue": "sara@old.example.com",
"newValue": "sara@example.com",
"type": "updated"
}
],
"metadata": null,
"timestamp": "Sep 14, 2026, 10:05 AM",
"summary": "Email changed from \"sara@old.example.com\" to \"sara@example.com\"\nin Contacts: Sara Ali\nby Omar Hassan"
}
]
}
Send request
Use the documented inputs to call this endpoint directly.
Parameters
Values are applied to the request and the example on the right.
Responses
Successful response
{
"id": 1.5,
"action": "string",
"field_name": "string",
"old_value": "string",
"new_value": "string",
"record_name": "string",
"record_type": "string",
"object_slug": "string",
"data_slug": "string",
"performed_by": "string",
"ip_address": "string",
"source_type": "string",
"action_category": "string",
"changes": "string",
"metadata": "string",
"timestamp": "string",
"summary": "string"
}Structured extras a writer attached for clients, keyed as they stored them.
old_value / new_value are the first CHANGE's scalar values, not the
stored objects — so rawData, and everything a writer deliberately put
there for a reader, never reached the client. Lead distribution stamps
_distribution (rule name, method) and _decision_trace (why a lead went
where it did) precisely so its Logs view can render them; both were
silently dropped, leaving those columns and the trace button permanently
empty.
Only underscore-prefixed keys travel: that prefix is the existing
convention for "this is metadata for a reader", so the row's own column
values are not re-published here in a second shape. null when the writer
attached none, which is the common case.
Bad request
{
"status": 1,
"message": "string",
"code": "string",
"data": {}
}The HTTP status code of the response.
What went wrong. Several validation messages are joined with ", ".
A stable, machine-readable reason. Only some errors set it.
Extra detail about the error. Only some errors set it.
Unauthorized
{
"status": 1,
"message": "string",
"code": "string",
"data": {}
}The HTTP status code of the response.
What went wrong. Several validation messages are joined with ", ".
A stable, machine-readable reason. Only some errors set it.
Extra detail about the error. Only some errors set it.
Internal server error
{
"status": 1,
"message": "string",
"code": "string",
"data": {}
}The HTTP status code of the response.
What went wrong. Several validation messages are joined with ", ".
A stable, machine-readable reason. Only some errors set it.
Extra detail about the error. Only some errors set it.
Powered by heyo-docs