Profile management
GET/PUT/DELETE /v1/profile and /v1/profile/tags/:name and /v1/profile/prompt — read and edit personalization (financial profile, tags, custom prompt).
GET /v1/profile
Returns the personalization snapshot — what the agent currently knows about the user. Mirror of the REPL /profile command and minara profile show.
| Method | GET |
| Path | /v1/profile |
| Auth | Authorization: Bearer <token> required when GATEWAY_AUTH_TOKEN is set |
| Category | personalization |
Response 200:
{
"ok": true,
"data": {
"trading_summary": {
"platform_wallet_summary": "Cycle-aware swing trader. Spot: BTC accumulation in pullbacks. Perps: short-bias hedge on ETH across two subs.",
"reference_wallets_summary": null
},
"memories": [
{ "id": 1, "statement": "Prefers long-term BTC holds.", "subcategory": "preference", "created_at": "2026-04-13T10:00:00Z" }
],
"tags": [
{ "name": "Risk Profile", "value": "Balanced", "source": "user", "updated_at": "2026-04-13T10:00:00Z" }
],
"custom_prompt": "Respond in casual tone",
"settings": { "include_memories": true, "include_trading_summary": true, "include_tags": true }
}
}platform_wallet_summary is composed by the personalization rebuilder
from three sources: in-session trade_history, perps_fills (cross-sub
mirror of Minara /v1/perp-wallets/fills), and external_spot_activities
(Minara /v1/tx/cross-chain/activities). The LLM emits four fields
(overall + spotBreakdown + perpsBreakdown + reference wallets) and
the rebuilder stitches them into a single string with Spot: /
Perps: prefixes so downstream readers see one summary while still
being able to parse the per-surface chunks. See
Personalization rebuilder
for the full pipeline.
The tags[].source field has three possible values:
user— explicitly set by the user (REPL/profile set, CLIminara profile set, or RESTPUT /v1/profile/tags/:name).learned_preference— set by the preference-evolution system when a behavioral preference graduated and bridged to this tag.inferred— derived by the periodic personalization rebuilder from chat history.
Precedence order is user > learned_preference > inferred; lower-tier writes are silently skipped against higher-tier rows.
PUT /v1/profile/tags/:name
Set or update a single user tag. The :name path parameter accepts either the canonical tag name (e.g. Risk Profile) or a slug form (e.g. risk-profile); the URL must be percent-encoded.
| Method | PUT |
| Path | /v1/profile/tags/:name |
| Auth | Authorization: Bearer <token> required when GATEWAY_AUTH_TOKEN is set |
| Body | { "value": "Conservative" } or { "value": null } to clear |
| Category | personalization |
The write is always recorded with source: "user" regardless of any source field in the request body. API consumers cannot claim inferred or learned_preference provenance — those are reserved for the rebuilder and the preference system.
Response 200 (success):
{ "ok": true, "data": { "name": "Risk Profile", "value": "Conservative", "source": "user", "updated_at": "2026-04-17T10:23:00Z" } }Response 422 (unknown tag or invalid value):
{ "ok": false, "error": "Invalid value 'Reckless' for \"Risk Profile\". Allowed: Aggressive / Balanced / Conservative" }DELETE /v1/profile/tags/:name
Equivalent to PUT with { "value": null } — clears the tag while preserving the soft-delete marker so a subsequent inferred rebuild won't re-set it. Recorded with source: "user".
| Method | DELETE |
| Path | /v1/profile/tags/:name |
| Auth | Authorization: Bearer <token> required when GATEWAY_AUTH_TOKEN is set |
| Category | personalization |
Response 200:
{ "ok": true, "data": { "name": "Risk Profile", "value": null, "source": "user", "updated_at": "2026-04-17T10:23:00Z" } }PUT /v1/profile/prompt
Set the user's custom system-prompt addendum.
| Method | PUT |
| Path | /v1/profile/prompt |
| Auth | Authorization: Bearer <token> required when GATEWAY_AUTH_TOKEN is set |
| Body | { "text": "Respond in casual tone" } (max 2000 chars) |
| Category | personalization |
Response 200:
{ "ok": true, "data": { "custom_prompt": "Respond in casual tone" } }Response 413: returned when the request body is larger than ~8 KB (rejected before parsing).
Response 422: returned when text is missing, empty, not a string, or longer than 2000 characters.
DELETE /v1/profile/prompt
Clear the custom prompt.
| Method | DELETE |
| Path | /v1/profile/prompt |
| Auth | Authorization: Bearer <token> required when GATEWAY_AUTH_TOKEN is set |
| Category | personalization |
Response 200:
{ "ok": true, "data": { "custom_prompt": null } }Related endpoints
The following endpoints round out the Profile / Personalization surface and are documented on their own auto-generated pages:
POST /v1/profile/refresh— force a rebuild + runMinaraHistorySynconce.GET /v1/profile/trade-history-breakdown— three-source breakdown that powers the Financial Profile dashboard (local trades + perps fills + spot activities + last sync timestamp).GET / PUT /v1/profile/reference-wallets— watchlist of external wallet addresses; PUT validates EVM and Solana formats.GET /v1/financial-profile— rawfinancial_profilerow including the rebuilt summary, reference wallets, custom prompt, visibility flags, and rebuild cursors.GET / POST / PATCH / DELETE /v1/memory— memory CRUD withcategory=personalization+source=user_manualallow-list. Soft-delete + 30-day retention; restore viaPOST /v1/memory/:id/restore.GET /v1/memory/methodologiesandGET /v1/memory/trading-cases/stats— Trading-cases dashboard feeds (separate from the user profile — see memory.trading-cases for why they don't mix).
For the complete machine-readable surface, download the OpenAPI 3.1 spec.