Profiles, Sessions, and Jobs
Fetch a user's long-term memory profile, inspect a session timeline, and poll async ingestion jobs without guessing which endpoint does what.
These three endpoints are usually used together after you start writing or ingesting memory:
GET /v1/memory/profile/:userIdGET /v1/memory/session/:sessionIdGET /v1/memory/jobs/:jobId
If you are discovering RetainDB for the first time, the easiest mental model is:
- profile = long-lived memory for one user
- session = what happened in one conversation or run
- job = background processing state for async work
Which endpoint to use
User profile
Use GET /v1/memory/profile/:userId when you want the durable memory RetainDB has for a user across sessions.
Typical examples:
- preferences you wrote for a user
- facts learned over time
- profile-like context you want to inspect before retrieval
Session memories
Use GET /v1/memory/session/:sessionId when you want the timeline for one conversation, run, or thread.
This is the better endpoint when you are debugging a specific workflow and want to see what got attached to that session.
Job status
Use GET /v1/memory/jobs/:jobId after async ingest or bulk work when the write returned a job id and you want to know whether background processing finished.
Request shape
Get a user profile
Path parameter:
userId
Query parameters:
project— optional ifRETAINDB_PROJECTis set in your environmentmemory_types— optional comma-separated listinclude_pending— optional, defaults totrue
curl "https://api.retaindb.com/v1/memory/profile/demo-alex?project=retaindb-quickstart&include_pending=true" \
-H "Authorization: Bearer $RETAINDB_API_KEY"Get a session timeline
Path parameter:
sessionId
Query parameters:
project— optional ifRETAINDB_PROJECTis set in your environmentinclude_inactive— optionalinclude_pending— optional, defaults totrue
curl "https://api.retaindb.com/v1/memory/session/session-001?project=retaindb-quickstart&include_pending=true" \
-H "Authorization: Bearer $RETAINDB_API_KEY"Poll a job
Path parameter:
jobId
curl "https://api.retaindb.com/v1/memory/jobs/job_123" \
-H "Authorization: Bearer $RETAINDB_API_KEY"What the responses look like
Profile response
{
"user_id": "demo-alex",
"memories": [
{
"id": "mem_123",
"content": "Alex prefers short, direct answers",
"type": "preference",
"entities": [],
"importance": 0.86,
"confidence": 0.93,
"document_date": "2026-03-09T10:20:00.000Z"
}
],
"count": 1,
"include_pending": true,
"pending_overlay_count": 0
}Session response
{
"session_id": "session-001",
"memories": [
{
"id": "pending:job_123:0",
"content": "User asked for release notes in bullet form",
"type": "event",
"pending": true,
"job_id": "job_123",
"created_at": "2026-03-09T10:22:00.000Z"
}
],
"count": 1,
"include_pending": true,
"pending_overlay_count": 1
}Job response
{
"success": true,
"job": {
"id": "job_123",
"status": "processing"
}
}Good defaults
Start with these:
- always pass the same
projectyou used for the write - leave
include_pending=trueon while validating a new integration - use the profile endpoint for long-term memory and the session endpoint for debugging one run
When results look wrong
Check these in order:
- The
projectmatches the original write. - The
userIdorsessionIdreally is the same identifier your app used. - You did not disable
include_pendingwhile testing async writes. - You are looking at the right surface: profile for user-level memory, session for run-level memory.
Error cases you will actually hit
404on job polling usually means the job id is wrong or expired404on profile or session lookup often means the project reference is wrong403on job polling means the job belongs to a different org500usually means a backend failure, not “no memories found”
Next step
If you want to understand why pending entries can appear before full extraction completes, read read-after-write visibility. If you need to create memory first, go to memory write and bulk write.
Was this page helpful?
Your feedback helps us prioritize docs improvements weekly.