Korely

Context & facts

Get profile

Everything Korely currently knows about one end user, in a single call, their active typed facts, self-owned facts first, also grouped by predicate family. Deterministic, no model call.

GET /v1/profile

SDK: korely.get_profile(...). Where Get facts is a flat, filterable list across all your end users, a profile is always per end user: user_id is required. You get the active facts the user owns sorted first, plus a by_family grouping ready to render. It is a pure filter-and-sort, no embeddings, no LLM.

Authentication

HTTP header, required: Authorization: Bearer kor_live_.... The key must carry the memories:read scope.

Query parameters

user_id is required, a profile is built for exactly one end user. The rest are optional.

ParameterTypeRequiredDefaultDescription
user_idstringRequiredNoneThe end user to build the profile for. Length 1-255 characters.
agent_idstringOptionalNoneFilter to one agent namespace.
as_ofstringOptionalNoneISO date or datetime, return the profile as it was on that date. A bare date (2026-06-01) means midnight; naive values are coerced to UTC.
known_as_ofstringOptionalNoneISO date or datetime, the profile as the store knew it then: the facts it had learned by that moment, each with the end it had learned by then, true at as_of (by default, at known_as_of itself). Parsed like as_of. See Temporal facts.
exclude_sessionsbooleanOptionalfalseLeave out the facts that only work sessions state: the memories written with kind: "session", what a coding assistant's hooks save. See Work sessions.

Example request

Terminal window
curl -G https://api.korely.ai/v1/profile \
-H "Authorization: Bearer kor_live_..." \
--data-urlencode "user_id=customer-giulia-4812"
# The profile as the store knew it on 20 September
curl -G https://api.korely.ai/v1/profile \
-H "Authorization: Bearer kor_live_..." \
--data-urlencode "user_id=customer-giulia-4812" \
--data-urlencode "known_as_of=2026-09-20"

Response

200 OK. The end user's facts true now or at as_of (with known_as_of, as the store knew them then), self-owned first, then the most recently confirmed first (last_confirmed_at, else valid_from, descending; with as_of or known_as_of, valid_from descending), plus the same facts grouped by predicate family.

{
"user_id": "customer-giulia-4812",
"as_of": null,
"known_as_of": null,
"facts": [
{
"id": "fct_3b9e1d7a5c2f4e8a9d6b0c1f7a2e4d85",
"subject": "customer-giulia-4812",
"subject_type": "person",
"predicate": "lives_in",
"predicate_raw": "lives in",
"object": "Berlin",
"object_is_literal": false,
"predicate_family": "places",
"confidence": 0.95,
"user_id": "customer-giulia-4812",
"agent_id": "support-bot",
"valid_from": "2026-04-10T00:00:00+00:00",
"invalid_at": null,
"invalidated_by": null,
"source_memory_id": "mem_8f2c1a0b9d3e4f5a6b7c8d9e0f1a2b3c",
"created_at": "2026-04-10T08:00:00+00:00",
"closed_known_at": null,
"subject_canonical": "customer-giulia-4812",
"object_canonical": "Berlin",
"tense": "current",
"last_confirmed_at": "2026-04-10T00:00:00+00:00",
"observation_count": 1,
"source_memory_ids": ["mem_8f2c1a0b9d3e4f5a6b7c8d9e0f1a2b3c"]
}
],
"by_family": {
"places": [
{
"id": "fct_3b9e1d7a5c2f4e8a9d6b0c1f7a2e4d85",
"subject": "customer-giulia-4812",
"subject_type": "person",
"predicate": "lives_in",
"predicate_raw": "lives in",
"object": "Berlin",
"object_is_literal": false,
"predicate_family": "places",
"confidence": 0.95,
"user_id": "customer-giulia-4812",
"agent_id": "support-bot",
"valid_from": "2026-04-10T00:00:00+00:00",
"invalid_at": null,
"invalidated_by": null,
"source_memory_id": "mem_8f2c1a0b9d3e4f5a6b7c8d9e0f1a2b3c",
"created_at": "2026-04-10T08:00:00+00:00",
"closed_known_at": null,
"subject_canonical": "customer-giulia-4812",
"object_canonical": "Berlin",
"tense": "current",
"last_confirmed_at": "2026-04-10T00:00:00+00:00",
"observation_count": 1,
"source_memory_ids": ["mem_8f2c1a0b9d3e4f5a6b7c8d9e0f1a2b3c"]
}
]
},
"total": 1,
"truncated": false
}
FieldTypeDescription
user_idstringEcho of the end user the profile was built for.
as_ofstring · nullEcho of the as_of query string, raw and un-normalized, or null if you didn't send one.
known_as_ofstring · nullEcho of the known_as_of query string, the same way.
factsarray<object>A flat list of the serialized facts (same shape as Get facts), sorted self/own-subject first, then most recently confirmed first within each bucket.
facts[].idstringThe fact id (fct_ and 32 hex characters).
facts[].subjectstringThe subject of the triple.
facts[].subject_typestringFrom extraction: person, organization, product, place, concept, event or unknown. On a fact written with POST /v1/facts, what the caller sent (for example self).
facts[].predicatestringThe normalized predicate, e.g. lives_in.
facts[].predicate_rawstringThe predicate as it appeared in the source text, e.g. lives in.
facts[].objectstringThe object of the triple.
facts[].object_is_literalbooleantrue when the object is a literal value rather than an entity.
facts[].predicate_familystringThe family the predicate belongs to, e.g. places.
facts[].confidencenumber · nullExtraction confidence, 0-1.
facts[].user_id / facts[].agent_idstring · nullThe scope the fact belongs to (null if unscoped).
facts[].valid_fromstring · nullISO 8601, when the fact became true (bi-temporal valid time).
facts[].invalid_atstring · nullISO 8601, when the fact stops being true, or null. Non-null only for a known future end date, or with as_of for a fact that ended after that date.
facts[].invalidated_bystring · nullThe id of the fact that superseded this one, or null.
facts[].source_memory_idstring · nullThe memory this fact was first extracted from; null for a fact written with POST /v1/facts.
facts[].created_atstring · nullISO 8601, when the store learned the fact.
facts[].closed_known_atstring · nullISO 8601, when the store learned the fact had ended, or null. Non-null only next to a non-null invalid_at.
facts[].subject_canonical / facts[].object_canonicalstringThe subject's and the object's current names after aliases.
facts[].tensestringcurrent, past or planned.
facts[].last_confirmed_atstring · nullISO 8601, the latest time the fact was stated, by a memory or a direct write (when it was never restated, when it was first stated).
facts[].observation_countintegerHow many times the fact was asserted, by memories or by direct writes. Above 1 it was reconfirmed, not duplicated.
facts[].source_memory_idsarray<string>Every mem_ id that asserts the fact.
by_familyobject<string, array<object>>The same facts grouped by predicate_family. The key is other when a fact's family is null.
totalintegerTotal active facts for this end user. May exceed the number returned in facts because the profile is capped, see truncated.
truncatedbooleantrue when total exceeds the number of returned facts, i.e. the 200-fact profile cap was hit.

Errors

StatusCodeCause
401invalid_keyMissing or invalid Authorization header. Message: Invalid or missing API key: ..., then what is wrong; response carries WWW-Authenticate: Bearer.
403forbiddenThe API key lacks the memories:read scope (API key missing required scope(s): memories:read), or the key is confined to some end users and user_id names another one.
422invalid_requestuser_id is missing, empty, over 255 characters or holds a NUL byte; agent_id is empty, over 255 characters or holds a NUL byte; or as_of / known_as_of is not an ISO date or datetime. Message: as_of must be an ISO date (2026-06-01) or datetime, with the name of the parameter you sent; or as_of / known_as_of is outside the moments that can be stored (as_of is outside the moments that can be stored: from 0001-01-02 to 9999-12-30, in UTC, with the name of the parameter you sent).
429rate_limit_exceededPer-tier minute / hour / day request limit exceeded. Message: Rate limit exceeded (<limit>/<unit>): try again in <n> s; the response carries a Retry-After header.
429quota_exceededMonthly query quota (plus 10% grace) exhausted. The body carries code and message at the top level ("Monthly query limit reached: ... queries on the ... plan this month, plus a 10% grace. It starts again on ..."), and detail holds code, message, limit (the plan's figure), used and resets_at (00:00 UTC on the 1st). No Retry-After: read detail.resets_at.

Notes

  • Deterministic. No model or LLM call, a pure filter and sort. The same request returns the same profile every time.
  • Per end user. user_id is required. That's the difference from the flat Get facts list, a profile is always built for one end user.
  • Capped at 200. The profile returns at most 200 facts. When the end user has more, truncated is true and total reports the real count. For larger pulls use Get facts with limit / offset.
  • Self-owned first. Facts the end user owns are sorted to the front, those whose subject_type is self, or whose subject, as written or under its current name after a declared name, equals the user_id (case-insensitive, trimmed). Within each bucket the order of the query is kept: most recently confirmed first (last_confirmed_at, else valid_from), or valid_from descending with as_of or known_as_of.
  • Grouped for you. by_family buckets the same facts by predicate_family, falling back to the key other when a fact's family is null.
  • True facts only. Only the facts true now or at as_of (with known_as_of, as the store knew them then) are returned, there is no include_invalidated option on this endpoint.
  • Echoed dates. The as_of and known_as_of in the response echo the raw query strings; retrieval internally uses the normalized datetimes.

Related

  • Get facts, the flat, filterable list of typed facts, with as_of time travel.
  • Get context, the assembled recall block, facts and memories in one call.
  • SDK reference, the get_profile method and its arguments.