Developer Changelog
This changelog documents API changes, schema modifications, and other developer-relevant changes that may affect integrations with rotki.
Unreleased
Classified User Messages
Renamed Message:
legacyis nowuser_message. Consumers matching the old type name must migrate.Changed Message:
user_messageBesides
verbosityandvalue,datanow always carrieskeyandfields, and carriessubject, which isnullfor a message about no single location.keyis why the message happened, one ofbad_data,network,auth,unknown_asset,local_db,price,unsupportedorinternal.fieldsholds the unrendered data of that family, e.g.recordanderrorforbad_data.valuekeeps the rendered sentence.groupis the message’s identity,[verbosity, key, subject, ...]followed by the fields that family groups by. Messages with the samegroupare repeats of one problem.
Changed Endpoint:
GET /api/(version)/messagesThe response is now
{"messages": [...], "dropped": int}instead of{"errors": [...], "warnings": [...]}. Each entry ofmessagesis the same{"type": ..., "data": ...}object the websocket sends, instead of a string, pluscount, how many times it was sent while held, andlast_sent, the timestamp of its last send.droppedcounts the messages discarded to stay within bounds, each of which is written to the backend log.Every message type that could not be delivered over a websocket is now held here, whether the send failed, no client was connected, or the client disconnected before receiving it. Previously each of those three paths applied a different policy. Progress and status types are dropped, except a
progress_updatesmessage carrying a CSV import result. A state message is held only in its latest form per key (e.g.refresh_balancesper chain), and a repeating failure once with a count: auser_messageonce pergroup, keeping its newestvalue.
Changed Message:
exchange_unknown_assetNow also sent for unknown assets in bit2me balances, deposits/withdrawals and trades, cryptocom deposits/withdrawals and trades, and kraken ledger events. These previously arrived as
user_messageerrors.
No Available Indexers Websocket Message
Changed Message:
no_available_indexersChange: The
dataobject gained an optionalreasonkey. When it isetherscan_paid_key_requiredthe chain was refused by etherscan for the configured key and a paid etherscan API key is needed to query it.
Frontend Settings Moved To Their Own Resource
frontend_settings is now read and written on its own resource, as JSON, and only ever merged, so a client no longer deletes keys it does not know.
New Endpoint:
GET /api/(version)/settings/frontendReturns the frontend settings as a JSON object. A stored blob that is absent, empty, or not a JSON object reads as
{}.
New Endpoint:
PATCH /api/(version)/settings/frontendTakes
patch(keys to set) andremove(keys to delete) and applies them server-side, leaving other keys untouched. A key is replaced wholesale, not merged recursively. Key names must match[A-Za-z_][A-Za-z0-9_]*.Answers
true. Read the result back with the GET above.
Changed Endpoint:
GET /api/(version)/settingsfrontend_settingsis no longer part of the response. The same applies to the settings carried byPUT /settings, by login and by account creation. Callers must read it fromGET /settings/frontend.
Changed Endpoint:
PUT /api/(version)/settingsfrontend_settingsis no longer accepted and is rejected as an unknown field.PATCH /settings/frontendis the only way to write it.
Asset Search NFT Handling
Changed Endpoint:
POST /api/(version)/assets/search/levenshteinThe boolean
search_nftsis replaced bynft_handling, which takes'exclude'(the default, matchingsearch_nfts: false),'include'(matchingsearch_nfts: true) and the new'show_only'. Callers sendingsearch_nftsmust migrate; the field is no longer accepted.'show_only'searches nfts alone. It cannot be reproduced by filtering an'include'response: assets and nfts are searched by separate queries whose results are merged and truncated tolimittogether, so the nfts can be cut off entirely when enough assets sort ahead of them.
Docker Control Endpoint
The Docker deployment gains /_control, served by the starling proxy on the published port. It lets the frontend restart the backend, start or stop the MCP server, and choose whether MCP comes up with the backend tree, none of which had any path outside the desktop app (closes #2807).
New Endpoint:
GET /_controlReturns
{"available": true, "methods": [...]}when the endpoint is mounted, and404when it is not. Unauthenticated, so the frontend can decide whether to offer the controls before a user has logged in.Mounted only in Docker with
ROTKI_SESSION_KEYset. A deployment with no session authentication serves no control surface at all.
New Endpoint:
POST /_controlJSON-RPC 2.0, carrying
status,restart,startService,stopServiceandsetServiceAutostart.startandstopare refused:stopwould exit PID 1 and take the container with it.Authorized per request by forwarding the caller’s session cookie to
GET /api/1/session/validate.401when core refuses,503when core cannot be reached.restartacceptslogleveland nothing else. A caller-chosendata_directory/log_directoryis refused rather than ignored, since in a container those are fixed mounts.startService/stopServiceonly address services that allow manual control, which today meansmcpalone; core and colibri are not independently stoppable.setServiceAutostarttakes{"service": "mcp", "autostart": <bool>}and records whether MCP comes up with the backend tree from the next start on. It starts and stops nothing, and is refused for any other service. The preference is stored in<data_dir>/app.config.jsonas{"mcpAutoStart": <bool>}, the same file name and key the desktop app uses, so it survives a container recreate; with no file MCP stays down, the same default the desktop app ships. Each service’s current preference is reported asautostartin thestatusreply.
A validation core granted within the last two minutes is honoured if core later becomes unreachable, so a
restartwhose bring-up fails can still be retried from the UI. It is dropped immediately on a401, and never overrides a core that is answering.
Spam Token Endpoint Renamed
The spam token endpoint now supports both EVM and Solana tokens and has been renamed accordingly.
Renamed Endpoint:
/api/(version)/assets/evm/spam/is now/api/(version)/assets/spam/POSTandDELETEmethods now accept both EVM and Solana token identifiers.
1.42.0
Event Group Position Endpoint
A new endpoint to get the 0-based position of a history event group in the filtered and sorted list of groups. This is useful for navigating to a specific event in paginated views.
New Endpoint:
GET /api/(version)/history/events/positionRequired
group_identifierparameter specifying the group identifier to find the position of.Returns the 0-based position of the group in the filtered and sorted (timestamp DESC) list of groups.
Returns null if the group is not found.
ETH2 Staking Events Refetch Endpoint
A new endpoint to refetch ETH2 staking events and return a breakdown of newly added events.
New Endpoint:
POST /api/(version)/blockchains/eth2/events/refetchRequired
entry_typeparameter specifying which type of staking events to refetch. Valid values are"block_productions"and"eth_withdrawals".Optional
from_timestampandto_timestampparameters to restrict the time range of events to refetch.Optional
validator_indicesparameter, a list of validator indices to refetch events for.Optional
addressesparameter, a list of EVM addresses (fee recipients for block productions, withdrawal addresses for withdrawals) to refetch events for.validator_indicesandaddressescannot both be specified in the same request. If neither is provided, events for all tracked validators are refetched.Supports
async_queryfor background execution.resultreturns an object withtotal,per_validator, andper_addressbreakdowns of newly added event counts.per_addressmaps fee recipient addresses for block productions or withdrawal addresses for withdrawals.
History Events Filter State Markers Parameter
The history events filter now uses a state_markers list parameter instead of the customized_events_only boolean flag for filtering by event states.
Modified Endpoint:
POST /api/(version)/history/eventsRemoved
customized_events_onlyboolean parameter.Added
state_markerslist parameter that accepts any combination of marker values:"customized","profit adjustment","matched","imported from csv".Events matching any of the specified markers are returned (OR logic).
If
state_markersis not provided or is empty, no marker filtering is applied.Example:
{"state_markers": ["customized", "imported from csv"]}returns events with either marker.
CSV Import Marker for History Events
All history events imported via CSV now have the imported_from_csv state marker automatically applied. This allows the frontend and API consumers to identify which events originated from CSV imports.
Changes on historical balances queries
Historical balances queries (ERC20 balanecOf and native token balances) are now cached in the db for future retrieval. get_historical_balance is now deleted from chain/evm/manager.py
Use now:
evm_manager.node_inquirer.get_historical_native_balance
evm_manager.node_inquirer.get_historical_token_balance
Mass Delete History Events by Filter
The history events DELETE endpoint now supports deleting events using filter parameters in addition to specific identifiers.
Modified Endpoint:
DELETE /api/(version)/history/eventsNow accepts filter parameters (asset, from_timestamp, to_timestamp, event_types, location, etc.) to delete matching events.
All provided filters are combined (intersection) to determine which events to delete.
At least one filter parameter must be provided to prevent accidental mass deletion.
The
identifiersparameter is now optional when other filter parameters are provided.
Trigger Async Task
Bypasses the normal background task scheduling and runs a task immediately. Only supports triggering the historical balance processing and the asset movement matching tasks currently.
New Endpoint:
POST /api/(version)/tasks/triggerRequired
taskparameter specifying which task to run. Valid values arehistorical_balance_processingandasset_movement_matching.
Scheduler Control
Enables or disables the periodic task scheduler. This should be called by the frontend once initial data loading is complete (transaction decoding, balances fetch, asset movement matching, historical balance processing). This ensures background tasks that require exclusive database write access (like backup sync) don’t run during DB upgrades, migrations, and asset updates.
New Endpoint:
PUT /api/(version)/tasks/schedulerRequired
enabledparameter (boolean) specifying whether to enable or disable the scheduler.Example:
{"enabled": true}
Matching Asset Movements With Onchain Events
Exchange asset movement events may now be manually matched with specific onchain events via the API.
New Endpoint:
PUT /api/(version)/history/events/match/asset_movementsMatch asset movements with corresponding events or mark asset movements as having no match.
Required
asset_movementparameter specifying the DB identifier of the asset movement.Optional
matched_eventsparameter specifying the list of DB identifiers of events to match with the asset movement. The asset movement is marked as having no match if this parameter is omitted or an empty list.Example:
{"asset_movement": 123, "matched_events": [124]}
New Endpoint:
POST /api/(version)/history/events/match/asset_movementsFinds possible matches for a given asset movement within the specified time range.
Required
asset_movementparameter specifying the group identifier to find matches for.Required
time_rangeparameter specifying the time range in seconds to include.Optional
only_expected_assetsparameter indicating whether to limit the possible matches to only events with assets in the same collection as the asset movement’s asset. True by default.Example:
{"asset_movement": "ef2...69f", "time_range": 7200, "only_expected_assets": true}
New Endpoint:
GET /api/(version)/history/events/match/asset_movementsOptional
only_ignoredflag indicating whether to return a list of the movements that are marked as having no match, or the list of all movements that have not been matched or ignored yet.
New Endpoint:
DELETE /api/(version)/history/events/match/asset_movementsRequired
identifierparameter specifying the DB identifier of an asset movement or an event matched with an asset movement to unlink.Unlinks the asset movement from its matched event. This asset movement will now appear in the list of unmatched movements again.
Modified Endpoint:
POST /api/(version)/history/eventsNew optional
actual_group_identifierfield in the response, containing the actual group identifier of the event as stored in the DB. This preserves the actual group identifier when asset movements are combined with the group of their matched event for display as a single unit in the frontend.Replaced the
customizedflag with astateslist. Valid states arecustomized,profit adjustment,matched,imported from csv.
New Settings (new fields in both
PUTandPOSTon/api/(version)/settings) -asset_movement_amount_toleranceThe tolerance value used when matching asset movement amounts with onchain events. Must be a positive decimal number. Default is"0.000001". -asset_movement_time_rangeThe time range before/after the asset movement (depending on if its a deposit/withdrawal) in which to check for possible matching events. Default is 54000 (15 hours). Note: there is also a 1 hour tolerance on the other side of the asset movement, since some exchanges do not provide accurate timestamps. -suppress_missing_key_msg_servicesA list of services for which the missing api key WS message should be suppressed. Empty list by default.
Event/Group Identifier Renaming
The common identifier for groups of events (i.e. all events from a given EVM tx) is renamed from event_identifier to group_identifier.
Modified Endpoints:
POST,PUT, andPATCHon/api/(version)/history/events- Renamedevent_identifiertogroup_identifier.PUT /api/(version)/history/events/export- Renamedevent_identifierstogroup_identifiers.POST /api/(version)/history/debug- Renamedevent_identifiertogroup_identifier.POST /api/(version)/balances/historical/asset- Renamedlast_event_identifiertolast_group_identifier.POST /api/(version)/balances/historical/netvalue- Renamedlast_event_identifiertolast_group_identifier.
Historical Balance Metrics
Historical balance data is now computed via an API task and stored in the event_metrics table.
Modified Endpoint:
POST /api/(version)/balances/historical/assetRemoved
last_group_identifierfrom response. Negative balance detection is now handled by the periodic task.
1.41.1
Runtime Log Level Modification
The backend log level may now be modified at runtime without restarting.
Modified Endpoint:
GET /api/(version)/settings/configurationNow includes a
loglevelfield in responseExample:
{"loglevel": {"value": "DEBUG", "is_default": true}, ...}
New Endpoint:
PUT /api/(version)/settings/configurationCurrently only supports the
loglevelparameterAccepted values:
TRACE,DEBUG,INFO,WARNING,ERROR,CRITICALReturns the same format as the GET endpoint.
ERC-721 (NFT) Token IDs
ERC-721 token IDs may now be set when adding/editing assets.
Modified Endpoint:
PUT /api/(version)/assets/allSupports a new
collectible_idfield. Only valid when token_kind is"erc721".
Modified Endpoint:
GET /api/(version)/assets/allNow includes a
collectible_idfield in the response when token_kind is"erc721".