User runtime object.
Verified against lua-cli 3.33.0.
Base URL and authentication
Reads needknowledge:read and writes knowledge:write on the agent; the host, the bearer header, and the error envelope are on the REST API overview. The two profile lookups are authorized by the handler as the key’s owner, which a scoped key cannot stand in for: call them with a user session or a legacy key. Records are not partitioned by environment; sandbox and production share them.
The record
A record is{ userId, agentId, data, createdAt, updatedAt }, with data the JSON bag your tools wrote and timestamps as Unix time in milliseconds. Reads that find the end user’s Lua profile add _luaProfile, a read-only object the platform maintains; it is never part of data. The routes under /developer/user/data/... unwrap the record and answer data itself with userId added, so a field of yours named userId is overwritten in that answer.
Writes merge at the top level: PUT shallow-merges the body’s keys into data (incoming wins, null is stored as a value, nothing is deleted) and creates the record when it is missing; PATCH sets and unsets named top-level keys atomically and needs an existing record.
Endpoints
GET /developer/user/data/agent/:agentId
Returns the caller’s own record on the agent, unwrapped.string
required
The agent.
200 with data’s fields, plus userId and, when available, _luaProfile. A missing record answers { "userId" } alone; nothing is created by a read.
Equivalent: User.get() inside a tool.
GET /developer/user/data/agent/:agentId/user/:userId
Returns a named end user’s record on the agent, unwrapped, in the same shape.string
required
The agent.
string
required
The end user.
User.get('<userId>').
PUT /developer/user/data/agent/:agentId
Merges the body into the caller’s record, creating it when missing.string
required
The agent.
object
required
Any JSON object. Top-level keys are shallow-merged into
data; nested objects are replaced whole.200 with the merged data plus userId.
Errors
Equivalent:
user.update({ plan: 'pro' }).
PUT /developer/user/data/agent/:agentId/user/:userId
Merges the body into a named end user’s record, with the same body, response, and errors.PATCH /developer/user/data/agent/:agentId
Sets and unsets top-level keys of the caller’s record in one atomic write.string
required
The agent.
object
Keys to write;
null is stored as a value.string[]
Keys to remove.
200 with the resulting data plus userId.
Errors
Equivalent:
user.patch({ set: { tier: 'gold' }, unset: ['trialEndsAt'] }).
PATCH /developer/user/data/agent/:agentId/user/:userId
Same mutation on a named end user’s record.PATCH /developer/agents/:agentId/user-data/:userId is an alias with identical behavior.
DELETE /developer/user/data/agent/:agentId
Deletes the caller’s record on the agent.string
required
The agent.
200 with an empty body when a record was deleted, or with { "message": "Agent data deleted successfully" } when no record existed; both are success.
Equivalent: user.clear().
DELETE /developer/user/data/agent/:agentId/user/:userId
Deletes a named end user’s record.DELETE /developer/agents/:agentId/user-data/:userId is an alias.
GET /developer/agents/:agentId/user-data
Lists the agent’s records, most recently updated first, with the profile of each end user when known.string
required
The agent.
integer
default:"1"
Page number from 1.
integer
default:"20"
From 1 to 100.
string
Matches end-user ids and profile fields. When the profile search hits its cap the answer carries
searchTruncated: true.200 with { "data": [...], "pagination": { ... }, "searchTruncated"? }; each item is a full record with _luaProfile when known, and pagination carries currentPage, totalPages, totalCount, limit, hasNextPage, and hasPrevPage.
Errors
GET /developer/agents/:agentId/user-data/capabilities
Tells a client whether the caller may write user data on this agent, so a UI can hide its editor. Response200 with { "canWrite": true | false }.
GET /developer/agents/:agentId/user-data/:userId
Returns one record wrapped,{ userId, agentId, data, createdAt, updatedAt, _luaProfile? }.
Errors
GET /developer/user/profile/email/:email
Resolves an email address to an end user who has talked to one of your agents.string
required
The address, URL-encoded; matching is case-insensitive.
string
Limit the lookup to one agent you can access.
200 with the end user’s profile, including id.
Errors
Equivalent:
User.get({ email: '[email protected]' }).
GET /developer/user/profile/phone/:phone
Resolves a phone number the same way. A leading+ is optional.
Equivalent: User.get({ phone: '+15551234567' }).
See also
User— the same record from agent code- Identify users — how an end user gets an id on each channel
- Custom data — agent-wide collections instead of per-user records
- REST API overview — authentication, scopes, and the error envelope

