This makes it harder for the UI, Java client, Python client, and future SDKs to rely on a stable API contract.
Expand to show specification
Memind Server API Format
Status: proposed v1 contract for memind-server.
This document defines the HTTP and OpenAPI contract for all
/open/v1/* and /admin/v1/* endpoints. It is the API shape that UI,
generated clients, Java clients, Python integrations, and future SDKs
should rely on.
Goals
- Provide one response format for success responses.
- Provide one response format for error responses.
- Keep HTTP status codes and Memind error codes separate.
- Standardize pagination, timestamps, request IDs, and field naming.
- Make async endpoints explicit about accepted work versus completed work.
- Make generated OpenAPI clients predictable.
Scope
This standard applies to every JSON endpoint under:
It does not define authentication, gateway behavior, or business logic
semantics.
Core Rules
- HTTP status codes describe transport, protocol, and resource outcome.
- Memind error codes describe domain or application error semantics.
- Success responses do not contain a business
code.
- Error responses contain
error.code; this value is not an HTTP status.
- JSON API endpoints should not use
204 No Content; return a standard
success envelope with data: null instead.
- Every response includes
meta.requestId and meta.timestamp.
- If the request includes
X-Request-Id, the server echoes it in
meta.requestId and the response X-Request-Id header. Otherwise the
server generates one.
Response Envelopes
ApiResult
ApiResult<T> is the success envelope. It means the HTTP request succeeded
and the response body contains the requested result.
{
"data": {
"status": "UP",
"service": "memind-server"
},
"meta": {
"requestId": "018f0d67-8a2d-7a8a-bb70-3f50ddde27f5",
"timestamp": "2026-05-11T08:00:00Z"
}
}
For commands that complete successfully but have no result:
{
"data": null,
"meta": {
"requestId": "018f0d67-8a2d-7a8a-bb70-3f50ddde27f5",
"timestamp": "2026-05-11T08:00:00Z"
}
}
ApiErrorResult
ApiErrorResult is the error envelope. It is used with non-2xx HTTP status
codes.
{
"error": {
"code": "validation_failed",
"message": "Request validation failed",
"details": {
"fieldErrors": {
"userId": "must not be blank"
}
}
},
"meta": {
"requestId": "018f0d67-8a2d-7a8a-bb70-3f50ddde27f5",
"timestamp": "2026-05-11T08:00:00Z"
}
}
error.details is optional. It should contain structured machine-readable
details when available, such as validation field errors.
Pagination
List endpoints return ApiResult<PageResult<T>>.
Request parameters:
page: 1-based page number. Default: 1.
pageSize: number of items per page. Default: endpoint-specific, normally
20. Maximum: 100 unless the endpoint documents a smaller limit.
Response:
{
"data": {
"items": [],
"page": {
"page": 1,
"pageSize": 20,
"totalItems": 123,
"totalPages": 7,
"hasPrevious": false,
"hasNext": true
}
},
"meta": {
"requestId": "018f0d67-8a2d-7a8a-bb70-3f50ddde27f5",
"timestamp": "2026-05-11T08:00:00Z"
}
}
PageResult<T> means:
items: the current page contents.
page.page: the current 1-based page number.
page.pageSize: requested page size after server validation.
page.totalItems: total number of matching items.
page.totalPages: ceil(totalItems / pageSize).
page.hasPrevious: whether a previous page exists.
page.hasNext: whether a next page exists.
Async Operations
Endpoints that complete work before responding return 200 OK.
Endpoints that accept work for later processing return 202 Accepted with an
operation result. 202 Accepted means the server accepted or durably queued
the request. It does not mean the business operation completed.
{
"data": {
"operationId": "op_01HX8Y3V4E8ZJ9N7M6Q5P4R3T2",
"status": "accepted",
"mode": "async"
},
"meta": {
"requestId": "018f0d67-8a2d-7a8a-bb70-3f50ddde27f5",
"timestamp": "2026-05-11T08:00:00Z"
}
}
Fire-and-forget endpoints that only schedule in-process work must not return
success unless the request has been persisted or otherwise made retry-safe.
Retry-aware clients must be able to distinguish accepted work from completed
work.
Standard HTTP Status and Error Codes
| HTTP status |
Error code |
Meaning |
| 400 |
bad_request |
Request cannot be processed because its shape or parameters are invalid. |
| 400 |
validation_failed |
Bean validation or semantic request validation failed. |
| 400 |
malformed_json |
Request body is not valid JSON or cannot be decoded. |
| 404 |
not_found |
Requested resource does not exist. |
| 409 |
conflict |
Request conflicts with current server state. |
| 409 |
version_conflict |
Optimistic locking or expected version check failed. |
| 415 |
unsupported_media_type |
Request content type is not supported. |
| 429 |
rate_limited |
Caller exceeded an enforced rate limit. Reserved until rate limiting exists. |
| 500 |
internal_error |
Unexpected server failure. |
| 503 |
runtime_unavailable |
Memory runtime is not ready or cannot serve requests. |
| 503 |
dependency_unavailable |
Required external dependency is unavailable. |
Rules:
- Do not use numeric strings such as
"200" or "500" as Memind error
codes.
- Do not return
200 OK with an error envelope.
- Do not return a success envelope for failed async work.
- Use the most specific code available.
internal_error is only for unexpected server bugs or uncategorized
failures.
Naming Conventions
- JSON fields use
camelCase.
- Query parameters use
camelCase.
- Resource identifiers use the domain suffix:
userId, agentId,
rawDataId, itemId, insightId, threadKey.
- Collection fields use plural names, normally
items.
- Paginated collections always use
data.items, never data.list.
- Timestamps are ISO-8601 strings in UTC, for example
2026-05-11T08:00:00Z.
- Public enum values should use
lower_snake_case. If internal Java enums use
UPPER_SNAKE_CASE, translate them at the API boundary.
- Optional fields may be omitted when unset. Required nullable fields must be
marked as nullable in OpenAPI.
OpenAPI Requirements
Every operation must define:
operationId
tags
summary
- Request schema, if the operation accepts a body.
- Query and path parameters with validation limits.
- One success response schema and example.
- Common error responses:
400, 404 where applicable, 409 where
applicable, 500, and 503.
Reusable schemas should be declared once under components.schemas.
components:
schemas:
ResponseMeta:
type: object
required: [requestId, timestamp]
properties:
requestId:
type: string
timestamp:
type: string
format: date-time
ApiResult:
type: object
required: [data, meta]
properties:
data:
nullable: true
meta:
$ref: '#/components/schemas/ResponseMeta'
ApiError:
type: object
required: [code, message]
properties:
code:
type: string
message:
type: string
details:
type: object
additionalProperties: true
ApiErrorResult:
type: object
required: [error, meta]
properties:
error:
$ref: '#/components/schemas/ApiError'
meta:
$ref: '#/components/schemas/ResponseMeta'
PageMeta:
type: object
required: [page, pageSize, totalItems, totalPages, hasPrevious, hasNext]
properties:
page:
type: integer
minimum: 1
pageSize:
type: integer
minimum: 1
maximum: 100
totalItems:
type: integer
format: int64
minimum: 0
totalPages:
type: integer
minimum: 0
hasPrevious:
type: boolean
hasNext:
type: boolean
PageResult:
type: object
required: [items, page]
properties:
items:
type: array
items: {}
page:
$ref: '#/components/schemas/PageMeta'
OperationAccepted:
type: object
required: [operationId, status, mode]
properties:
operationId:
type: string
status:
type: string
enum: [accepted]
mode:
type: string
enum: [async]
OpenAPI does not support Java-style generics directly. For each endpoint,
compose ApiResult with the concrete data schema in the operation response.
For example, GET /open/v1/health should document data as
OpenMemoryHealth.
Polymorphic request or response types must use oneOf with a discriminator.
This is required for raw content, content blocks, and source payloads.
Client Contract
Clients must:
- Treat 2xx HTTP responses as successful transport outcomes.
- Parse successful responses from
data.
- Treat
202 Accepted as accepted asynchronous work, not completed work.
- Treat non-2xx responses as errors and parse
error.
- Preserve and surface
meta.requestId for diagnostics.
Clients must not:
- Decide success by comparing a body field to
"success" or "200".
- Expect error details in
data.
- Retry all failures blindly. Retry policy should use HTTP status and
endpoint semantics.
Recommended retry behavior:
- Retry transport failures, timeouts,
429, and 503 when the operation is
idempotent or has an idempotency key.
- Do not retry
400, 404, or validation failures without changing the
request.
- Do not mark async write operations as completed after
202 Accepted.
Versioning
- The major API version is encoded in the URL:
/open/v1 and /admin/v1.
- Backward-incompatible wire changes require a new major URL version.
- Additive fields are allowed in the same version.
- Removing fields, renaming fields, changing field types, or changing enum
values is breaking.
- Deprecated fields must be marked with
deprecated: true in OpenAPI and kept
until the next major API version.
/open/v1/* is a public client contract.
/admin/v1/* is primarily for the UI, but it must still follow this
document so generated clients and contract tests remain reliable.
Endpoint Examples
Health
{
"data": {
"status": "up",
"service": "memind-server"
},
"meta": {
"requestId": "018f0d67-8a2d-7a8a-bb70-3f50ddde27f5",
"timestamp": "2026-05-11T08:00:00Z"
}
}
Retrieve Memory
POST /open/v1/memory/retrieve
{
"userId": "user-1",
"agentId": "agent-1",
"query": "What does the user prefer for backend architecture?",
"strategy": "simple",
"trace": false
}
{
"data": {
"status": "completed",
"items": [],
"insights": [],
"rawData": [],
"evidences": [],
"strategy": "simple",
"query": "What does the user prefer for backend architecture?",
"trace": null
},
"meta": {
"requestId": "018f0d67-8a2d-7a8a-bb70-3f50ddde27f5",
"timestamp": "2026-05-11T08:00:00Z"
}
}
Admin Page
GET /admin/v1/items?page=1&pageSize=20&userId=user-1
{
"data": {
"items": [],
"page": {
"page": 1,
"pageSize": 20,
"totalItems": 0,
"totalPages": 0,
"hasPrevious": false,
"hasNext": false
}
},
"meta": {
"requestId": "018f0d67-8a2d-7a8a-bb70-3f50ddde27f5",
"timestamp": "2026-05-11T08:00:00Z"
}
}
Migration Checklist
Use this checklist when implementing the standard:
- Replace success response bodies with
ApiResult<T> using data and meta.
- Replace error response bodies with
ApiErrorResult.
- Remove success business codes such as
"success" and "200" from response
bodies.
- Move validation details from
data to error.details.
- Change pagination from
total/list/current to items/page.
- Change list query parameters from
pageNo to page.
- Add request ID generation and response header echoing.
- Make async write endpoints return
202 Accepted only after durable
acceptance, or make them synchronous and return 200 OK only after
completion.
- Add OpenAPI schemas, examples, and common error responses.
- Update UI and SDK clients to rely on HTTP status and the new envelopes.
Contract Checks
The server should include automated checks that prevent new endpoints from
drifting from this standard:
- Controller return types are
ApiResult<T>,
ResponseEntity<ApiResult<T>>, or ResponseEntity<ApiErrorResult>.
- All exception handlers produce
ApiErrorResult.
- OpenAPI output contains the common response schemas.
- Every operation documents at least one 2xx response and the common error
responses.
- Paginated endpoints use
PageResult<T>.
- Error codes in OpenAPI match the standard error code list.
- Async endpoints never document
200 OK unless the work completes before the
response is sent.
Feature Request: Standardize Server OpenAPI Interface Format
Background
memind-servercurrently exposes/open/v1/*and/admin/v1/*APIs. Most endpoints already use shared responsemodels such as
ApiResult<T>andPageResult<T>, but the API format is not yet formally standardized across responsestructure, pagination, error codes, timestamps, and OpenAPI documentation.
This makes it harder for the UI, Java client, Python client, and future SDKs to rely on a stable API contract.
Goal
Define and enforce a consistent OpenAPI interface format for
memind-server.Scope
The standard should cover:
/open/v1/*and/admin/v1/*Acceptance Criteria
Non-goals
Expand to show specification
Memind Server API Format
Status: proposed v1 contract for
memind-server.This document defines the HTTP and OpenAPI contract for all
/open/v1/*and/admin/v1/*endpoints. It is the API shape that UI,generated clients, Java clients, Python integrations, and future SDKs
should rely on.
Goals
Scope
This standard applies to every JSON endpoint under:
/open/v1/*/admin/v1/*It does not define authentication, gateway behavior, or business logic
semantics.
Core Rules
code.error.code; this value is not an HTTP status.204 No Content; return a standardsuccess envelope with
data: nullinstead.meta.requestIdandmeta.timestamp.X-Request-Id, the server echoes it inmeta.requestIdand the responseX-Request-Idheader. Otherwise theserver generates one.
Response Envelopes
ApiResult
ApiResult<T>is the success envelope. It means the HTTP request succeededand the response body contains the requested result.
{ "data": { "status": "UP", "service": "memind-server" }, "meta": { "requestId": "018f0d67-8a2d-7a8a-bb70-3f50ddde27f5", "timestamp": "2026-05-11T08:00:00Z" } }For commands that complete successfully but have no result:
{ "data": null, "meta": { "requestId": "018f0d67-8a2d-7a8a-bb70-3f50ddde27f5", "timestamp": "2026-05-11T08:00:00Z" } }ApiErrorResult
ApiErrorResultis the error envelope. It is used with non-2xx HTTP statuscodes.
{ "error": { "code": "validation_failed", "message": "Request validation failed", "details": { "fieldErrors": { "userId": "must not be blank" } } }, "meta": { "requestId": "018f0d67-8a2d-7a8a-bb70-3f50ddde27f5", "timestamp": "2026-05-11T08:00:00Z" } }error.detailsis optional. It should contain structured machine-readabledetails when available, such as validation field errors.
Pagination
List endpoints return
ApiResult<PageResult<T>>.Request parameters:
page: 1-based page number. Default:1.pageSize: number of items per page. Default: endpoint-specific, normally20. Maximum:100unless the endpoint documents a smaller limit.Response:
{ "data": { "items": [], "page": { "page": 1, "pageSize": 20, "totalItems": 123, "totalPages": 7, "hasPrevious": false, "hasNext": true } }, "meta": { "requestId": "018f0d67-8a2d-7a8a-bb70-3f50ddde27f5", "timestamp": "2026-05-11T08:00:00Z" } }PageResult<T>means:items: the current page contents.page.page: the current 1-based page number.page.pageSize: requested page size after server validation.page.totalItems: total number of matching items.page.totalPages:ceil(totalItems / pageSize).page.hasPrevious: whether a previous page exists.page.hasNext: whether a next page exists.Async Operations
Endpoints that complete work before responding return
200 OK.Endpoints that accept work for later processing return
202 Acceptedwith anoperation result.
202 Acceptedmeans the server accepted or durably queuedthe request. It does not mean the business operation completed.
{ "data": { "operationId": "op_01HX8Y3V4E8ZJ9N7M6Q5P4R3T2", "status": "accepted", "mode": "async" }, "meta": { "requestId": "018f0d67-8a2d-7a8a-bb70-3f50ddde27f5", "timestamp": "2026-05-11T08:00:00Z" } }Fire-and-forget endpoints that only schedule in-process work must not return
success unless the request has been persisted or otherwise made retry-safe.
Retry-aware clients must be able to distinguish accepted work from completed
work.
Standard HTTP Status and Error Codes
bad_requestvalidation_failedmalformed_jsonnot_foundconflictversion_conflictunsupported_media_typerate_limitedinternal_errorruntime_unavailabledependency_unavailableRules:
"200"or"500"as Memind errorcodes.
200 OKwith an error envelope.internal_erroris only for unexpected server bugs or uncategorizedfailures.
Naming Conventions
camelCase.camelCase.userId,agentId,rawDataId,itemId,insightId,threadKey.items.data.items, neverdata.list.2026-05-11T08:00:00Z.lower_snake_case. If internal Java enums useUPPER_SNAKE_CASE, translate them at the API boundary.marked as nullable in OpenAPI.
OpenAPI Requirements
Every operation must define:
operationIdtagssummary400,404where applicable,409whereapplicable,
500, and503.Reusable schemas should be declared once under
components.schemas.OpenAPI does not support Java-style generics directly. For each endpoint,
compose
ApiResultwith the concretedataschema in the operation response.For example,
GET /open/v1/healthshould documentdataasOpenMemoryHealth.Polymorphic request or response types must use
oneOfwith a discriminator.This is required for raw content, content blocks, and source payloads.
Client Contract
Clients must:
data.202 Acceptedas accepted asynchronous work, not completed work.error.meta.requestIdfor diagnostics.Clients must not:
"success"or"200".data.endpoint semantics.
Recommended retry behavior:
429, and503when the operation isidempotent or has an idempotency key.
400,404, or validation failures without changing therequest.
202 Accepted.Versioning
/open/v1and/admin/v1.values is breaking.
deprecated: truein OpenAPI and keptuntil the next major API version.
/open/v1/*is a public client contract./admin/v1/*is primarily for the UI, but it must still follow thisdocument so generated clients and contract tests remain reliable.
Endpoint Examples
Health
{ "data": { "status": "up", "service": "memind-server" }, "meta": { "requestId": "018f0d67-8a2d-7a8a-bb70-3f50ddde27f5", "timestamp": "2026-05-11T08:00:00Z" } }Retrieve Memory
{ "userId": "user-1", "agentId": "agent-1", "query": "What does the user prefer for backend architecture?", "strategy": "simple", "trace": false }{ "data": { "status": "completed", "items": [], "insights": [], "rawData": [], "evidences": [], "strategy": "simple", "query": "What does the user prefer for backend architecture?", "trace": null }, "meta": { "requestId": "018f0d67-8a2d-7a8a-bb70-3f50ddde27f5", "timestamp": "2026-05-11T08:00:00Z" } }Admin Page
{ "data": { "items": [], "page": { "page": 1, "pageSize": 20, "totalItems": 0, "totalPages": 0, "hasPrevious": false, "hasNext": false } }, "meta": { "requestId": "018f0d67-8a2d-7a8a-bb70-3f50ddde27f5", "timestamp": "2026-05-11T08:00:00Z" } }Migration Checklist
Use this checklist when implementing the standard:
ApiResult<T>usingdataandmeta.ApiErrorResult."success"and"200"from responsebodies.
datatoerror.details.total/list/currenttoitems/page.pageNotopage.202 Acceptedonly after durableacceptance, or make them synchronous and return
200 OKonly aftercompletion.
Contract Checks
The server should include automated checks that prevent new endpoints from
drifting from this standard:
ApiResult<T>,ResponseEntity<ApiResult<T>>, orResponseEntity<ApiErrorResult>.ApiErrorResult.responses.
PageResult<T>.200 OKunless the work completes before theresponse is sent.