Префикс /api/v1, operationId = "<tag>_<name>", чтобы Dart-клиент получил методы вроде accountsList, а не list_accounts_api_v1_accounts_get. Ошибки — application/problem+json. Auth: access-JWT на час + refresh на 30 дней, который хранится хэшем и ротируется, логин ограничен по частоте в памяти. Деньги в JSON — всегда позиционные строки (api/schemas/common.py): float в проводе потерял бы копейки, которые NUMERIC(24,10) бережёт. Тестовый harness поднимает свой Postgres через pg_ctl (pytest-postgresql), мигрирует его один раз на сессию и усекает таблицы после каждого теста.
2964 lines
70 KiB
JSON
2964 lines
70 KiB
JSON
{
|
|
"components": {
|
|
"schemas": {
|
|
"AccountBalance": {
|
|
"properties": {
|
|
"account_id": {
|
|
"title": "Account Id",
|
|
"type": "integer"
|
|
},
|
|
"balance": {
|
|
"description": "decimal as string",
|
|
"title": "Balance",
|
|
"type": "string"
|
|
},
|
|
"balance_rub": {
|
|
"anyOf": [
|
|
{
|
|
"description": "decimal as string",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Balance Rub"
|
|
},
|
|
"currency": {
|
|
"title": "Currency",
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"title": "Name",
|
|
"type": "string"
|
|
},
|
|
"role": {
|
|
"$ref": "#/components/schemas/AccountRole"
|
|
}
|
|
},
|
|
"required": [
|
|
"account_id",
|
|
"name",
|
|
"currency",
|
|
"role",
|
|
"balance",
|
|
"balance_rub"
|
|
],
|
|
"title": "AccountBalance",
|
|
"type": "object"
|
|
},
|
|
"AccountKind": {
|
|
"enum": [
|
|
"zm_cash",
|
|
"zm_card",
|
|
"zm_checking",
|
|
"zm_deposit",
|
|
"zm_loan",
|
|
"zm_emoney",
|
|
"zm_debt",
|
|
"broker",
|
|
"manual_asset"
|
|
],
|
|
"title": "AccountKind",
|
|
"type": "string"
|
|
},
|
|
"AccountOut": {
|
|
"properties": {
|
|
"archived": {
|
|
"title": "Archived",
|
|
"type": "boolean"
|
|
},
|
|
"balance": {
|
|
"anyOf": [
|
|
{
|
|
"description": "decimal as string",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Balance"
|
|
},
|
|
"balance_as_of": {
|
|
"anyOf": [
|
|
{
|
|
"format": "date-time",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Balance As Of"
|
|
},
|
|
"broker": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/components/schemas/Broker"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
]
|
|
},
|
|
"credit_limit": {
|
|
"anyOf": [
|
|
{
|
|
"description": "decimal as string",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Credit Limit"
|
|
},
|
|
"currency": {
|
|
"title": "Currency",
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"title": "Id",
|
|
"type": "integer"
|
|
},
|
|
"include_in_net_worth": {
|
|
"title": "Include In Net Worth",
|
|
"type": "boolean"
|
|
},
|
|
"kind": {
|
|
"$ref": "#/components/schemas/AccountKind"
|
|
},
|
|
"mirror_of_account_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "integer"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Mirror Of Account Id"
|
|
},
|
|
"name": {
|
|
"title": "Name",
|
|
"type": "string"
|
|
},
|
|
"opened_at": {
|
|
"anyOf": [
|
|
{
|
|
"format": "date",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Opened At"
|
|
},
|
|
"primary_event_source": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/components/schemas/EventSource"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
]
|
|
},
|
|
"role": {
|
|
"$ref": "#/components/schemas/AccountRole"
|
|
},
|
|
"source": {
|
|
"title": "Source",
|
|
"type": "string"
|
|
},
|
|
"source_id": {
|
|
"title": "Source Id",
|
|
"type": "string"
|
|
},
|
|
"start_balance": {
|
|
"anyOf": [
|
|
{
|
|
"description": "decimal as string",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Start Balance"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"kind",
|
|
"source",
|
|
"source_id",
|
|
"broker",
|
|
"name",
|
|
"currency",
|
|
"role",
|
|
"include_in_net_worth",
|
|
"mirror_of_account_id",
|
|
"primary_event_source",
|
|
"archived",
|
|
"opened_at",
|
|
"balance",
|
|
"balance_as_of",
|
|
"start_balance",
|
|
"credit_limit"
|
|
],
|
|
"title": "AccountOut",
|
|
"type": "object"
|
|
},
|
|
"AccountPatch": {
|
|
"additionalProperties": false,
|
|
"description": "Only the fields the user owns: everything else comes from the source on each sync.\n\nUnset fields are left alone; an explicit `null` clears the column.",
|
|
"properties": {
|
|
"include_in_net_worth": {
|
|
"anyOf": [
|
|
{
|
|
"type": "boolean"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Include In Net Worth"
|
|
},
|
|
"mirror_of_account_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "integer"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Mirror Of Account Id"
|
|
},
|
|
"name": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Name"
|
|
},
|
|
"primary_event_source": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/components/schemas/EventSource"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
]
|
|
},
|
|
"role": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/components/schemas/AccountRole"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"title": "AccountPatch",
|
|
"type": "object"
|
|
},
|
|
"AccountRole": {
|
|
"enum": [
|
|
"liquid",
|
|
"savings",
|
|
"investment",
|
|
"debt"
|
|
],
|
|
"title": "AccountRole",
|
|
"type": "string"
|
|
},
|
|
"Broker": {
|
|
"enum": [
|
|
"tinvest",
|
|
"sber",
|
|
"vtb",
|
|
"other"
|
|
],
|
|
"title": "Broker",
|
|
"type": "string"
|
|
},
|
|
"CashFlowMonth": {
|
|
"properties": {
|
|
"baseline_rub": {
|
|
"description": "decimal as string",
|
|
"title": "Baseline Rub",
|
|
"type": "string"
|
|
},
|
|
"expense_rub": {
|
|
"description": "decimal as string",
|
|
"title": "Expense Rub",
|
|
"type": "string"
|
|
},
|
|
"income_rub": {
|
|
"description": "decimal as string",
|
|
"title": "Income Rub",
|
|
"type": "string"
|
|
},
|
|
"month": {
|
|
"format": "date",
|
|
"title": "Month",
|
|
"type": "string"
|
|
},
|
|
"one_off_rub": {
|
|
"description": "decimal as string",
|
|
"title": "One Off Rub",
|
|
"type": "string"
|
|
},
|
|
"savings_rate": {
|
|
"anyOf": [
|
|
{
|
|
"description": "decimal as string",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Savings Rate"
|
|
},
|
|
"savings_transfer_rub": {
|
|
"description": "decimal as string",
|
|
"title": "Savings Transfer Rub",
|
|
"type": "string"
|
|
},
|
|
"txn_count": {
|
|
"title": "Txn Count",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"month",
|
|
"income_rub",
|
|
"expense_rub",
|
|
"baseline_rub",
|
|
"one_off_rub",
|
|
"savings_transfer_rub",
|
|
"savings_rate",
|
|
"txn_count"
|
|
],
|
|
"title": "CashFlowMonth",
|
|
"type": "object"
|
|
},
|
|
"CategoryOut": {
|
|
"description": "Flat list; the client builds the tree from `parent_id` (ZenMoney nests one level).",
|
|
"properties": {
|
|
"archived": {
|
|
"title": "Archived",
|
|
"type": "boolean"
|
|
},
|
|
"color": {
|
|
"anyOf": [
|
|
{
|
|
"type": "integer"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Color"
|
|
},
|
|
"icon": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Icon"
|
|
},
|
|
"id": {
|
|
"title": "Id",
|
|
"type": "integer"
|
|
},
|
|
"name": {
|
|
"title": "Name",
|
|
"type": "string"
|
|
},
|
|
"parent_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "integer"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Parent Id"
|
|
},
|
|
"show_income": {
|
|
"title": "Show Income",
|
|
"type": "boolean"
|
|
},
|
|
"show_outcome": {
|
|
"title": "Show Outcome",
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"parent_id",
|
|
"name",
|
|
"icon",
|
|
"color",
|
|
"show_income",
|
|
"show_outcome",
|
|
"archived"
|
|
],
|
|
"title": "CategoryOut",
|
|
"type": "object"
|
|
},
|
|
"DataQualityRow": {
|
|
"properties": {
|
|
"check_name": {
|
|
"title": "Check Name",
|
|
"type": "string"
|
|
},
|
|
"computed_at": {
|
|
"format": "date-time",
|
|
"title": "Computed At",
|
|
"type": "string"
|
|
},
|
|
"count": {
|
|
"title": "Count",
|
|
"type": "integer"
|
|
},
|
|
"detail": {
|
|
"title": "Detail",
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"title": "Id",
|
|
"type": "integer"
|
|
},
|
|
"ref": {
|
|
"anyOf": [
|
|
{
|
|
"additionalProperties": true,
|
|
"type": "object"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Ref"
|
|
},
|
|
"severity": {
|
|
"title": "Severity",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"check_name",
|
|
"severity",
|
|
"detail",
|
|
"count",
|
|
"ref",
|
|
"computed_at"
|
|
],
|
|
"title": "DataQualityRow",
|
|
"type": "object"
|
|
},
|
|
"EventSource": {
|
|
"description": "Which feed is the truth for an account's ledger; others become `shadow` events.",
|
|
"enum": [
|
|
"tinvest_api",
|
|
"report_sber",
|
|
"report_vtb",
|
|
"manual"
|
|
],
|
|
"title": "EventSource",
|
|
"type": "string"
|
|
},
|
|
"FlowType": {
|
|
"enum": [
|
|
"income",
|
|
"expense",
|
|
"internal_transfer",
|
|
"savings_transfer",
|
|
"broker_external_flow",
|
|
"deleted",
|
|
"other"
|
|
],
|
|
"title": "FlowType",
|
|
"type": "string"
|
|
},
|
|
"Health": {
|
|
"properties": {
|
|
"database": {
|
|
"title": "Database",
|
|
"type": "string"
|
|
},
|
|
"status": {
|
|
"title": "Status",
|
|
"type": "string"
|
|
},
|
|
"version": {
|
|
"title": "Version",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"status",
|
|
"version",
|
|
"database"
|
|
],
|
|
"title": "Health",
|
|
"type": "object"
|
|
},
|
|
"JobStatus": {
|
|
"enum": [
|
|
"queued",
|
|
"running",
|
|
"done",
|
|
"error"
|
|
],
|
|
"title": "JobStatus",
|
|
"type": "string"
|
|
},
|
|
"LoginRequest": {
|
|
"properties": {
|
|
"email": {
|
|
"format": "email",
|
|
"title": "Email",
|
|
"type": "string"
|
|
},
|
|
"password": {
|
|
"maxLength": 1024,
|
|
"minLength": 1,
|
|
"title": "Password",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"email",
|
|
"password"
|
|
],
|
|
"title": "LoginRequest",
|
|
"type": "object"
|
|
},
|
|
"NetWorthBreakdown": {
|
|
"properties": {
|
|
"accounts": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/AccountBalance"
|
|
},
|
|
"title": "Accounts",
|
|
"type": "array"
|
|
},
|
|
"by_currency": {
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
},
|
|
"title": "By Currency",
|
|
"type": "object"
|
|
},
|
|
"d": {
|
|
"anyOf": [
|
|
{
|
|
"format": "date",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "D"
|
|
},
|
|
"debt_rub": {
|
|
"description": "decimal as string",
|
|
"title": "Debt Rub",
|
|
"type": "string"
|
|
},
|
|
"investment_rub": {
|
|
"description": "decimal as string",
|
|
"title": "Investment Rub",
|
|
"type": "string"
|
|
},
|
|
"liquid_rub": {
|
|
"description": "decimal as string",
|
|
"title": "Liquid Rub",
|
|
"type": "string"
|
|
},
|
|
"missing_fx_count": {
|
|
"title": "Missing Fx Count",
|
|
"type": "integer"
|
|
},
|
|
"savings_rub": {
|
|
"description": "decimal as string",
|
|
"title": "Savings Rub",
|
|
"type": "string"
|
|
},
|
|
"total_rub": {
|
|
"description": "decimal as string",
|
|
"title": "Total Rub",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"d",
|
|
"total_rub",
|
|
"liquid_rub",
|
|
"savings_rub",
|
|
"investment_rub",
|
|
"debt_rub",
|
|
"by_currency",
|
|
"missing_fx_count",
|
|
"accounts"
|
|
],
|
|
"title": "NetWorthBreakdown",
|
|
"type": "object"
|
|
},
|
|
"NetWorthDay": {
|
|
"properties": {
|
|
"by_currency": {
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
},
|
|
"title": "By Currency",
|
|
"type": "object"
|
|
},
|
|
"d": {
|
|
"format": "date",
|
|
"title": "D",
|
|
"type": "string"
|
|
},
|
|
"debt_rub": {
|
|
"description": "decimal as string",
|
|
"title": "Debt Rub",
|
|
"type": "string"
|
|
},
|
|
"investment_rub": {
|
|
"description": "decimal as string",
|
|
"title": "Investment Rub",
|
|
"type": "string"
|
|
},
|
|
"liquid_rub": {
|
|
"description": "decimal as string",
|
|
"title": "Liquid Rub",
|
|
"type": "string"
|
|
},
|
|
"missing_fx_count": {
|
|
"title": "Missing Fx Count",
|
|
"type": "integer"
|
|
},
|
|
"savings_rub": {
|
|
"description": "decimal as string",
|
|
"title": "Savings Rub",
|
|
"type": "string"
|
|
},
|
|
"total_rub": {
|
|
"description": "decimal as string",
|
|
"title": "Total Rub",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"d",
|
|
"total_rub",
|
|
"liquid_rub",
|
|
"savings_rub",
|
|
"investment_rub",
|
|
"debt_rub",
|
|
"by_currency",
|
|
"missing_fx_count"
|
|
],
|
|
"title": "NetWorthDay",
|
|
"type": "object"
|
|
},
|
|
"Problem": {
|
|
"description": "RFC 7807 error body (application/problem+json)",
|
|
"properties": {
|
|
"detail": {
|
|
"type": "string"
|
|
},
|
|
"errors": {
|
|
"items": {},
|
|
"type": "array"
|
|
},
|
|
"status": {
|
|
"type": "integer"
|
|
},
|
|
"title": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"status",
|
|
"title"
|
|
],
|
|
"title": "Problem",
|
|
"type": "object"
|
|
},
|
|
"RefreshLogOut": {
|
|
"properties": {
|
|
"error": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Error"
|
|
},
|
|
"finished_at": {
|
|
"anyOf": [
|
|
{
|
|
"format": "date-time",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Finished At"
|
|
},
|
|
"id": {
|
|
"title": "Id",
|
|
"type": "integer"
|
|
},
|
|
"started_at": {
|
|
"format": "date-time",
|
|
"title": "Started At",
|
|
"type": "string"
|
|
},
|
|
"trigger": {
|
|
"title": "Trigger",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"started_at",
|
|
"finished_at",
|
|
"trigger",
|
|
"error"
|
|
],
|
|
"title": "RefreshLogOut",
|
|
"type": "object"
|
|
},
|
|
"RefreshRequest": {
|
|
"properties": {
|
|
"refresh_token": {
|
|
"minLength": 1,
|
|
"title": "Refresh Token",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"refresh_token"
|
|
],
|
|
"title": "RefreshRequest",
|
|
"type": "object"
|
|
},
|
|
"RuleCreate": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"enabled": {
|
|
"default": true,
|
|
"title": "Enabled",
|
|
"type": "boolean"
|
|
},
|
|
"kind": {
|
|
"$ref": "#/components/schemas/RuleKind"
|
|
},
|
|
"match_type": {
|
|
"$ref": "#/components/schemas/RuleMatchType"
|
|
},
|
|
"note": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Note"
|
|
},
|
|
"pattern": {
|
|
"maxLength": 512,
|
|
"minLength": 1,
|
|
"title": "Pattern",
|
|
"type": "string"
|
|
},
|
|
"priority": {
|
|
"default": 100,
|
|
"title": "Priority",
|
|
"type": "integer"
|
|
},
|
|
"value": {
|
|
"anyOf": [
|
|
{
|
|
"maxLength": 512,
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Value"
|
|
}
|
|
},
|
|
"required": [
|
|
"kind",
|
|
"match_type",
|
|
"pattern"
|
|
],
|
|
"title": "RuleCreate",
|
|
"type": "object"
|
|
},
|
|
"RuleKind": {
|
|
"enum": [
|
|
"savings",
|
|
"one_off",
|
|
"category",
|
|
"payee",
|
|
"broker_target",
|
|
"ignore"
|
|
],
|
|
"title": "RuleKind",
|
|
"type": "string"
|
|
},
|
|
"RuleMatchType": {
|
|
"enum": [
|
|
"id",
|
|
"payee",
|
|
"comment",
|
|
"category",
|
|
"mcc",
|
|
"account"
|
|
],
|
|
"title": "RuleMatchType",
|
|
"type": "string"
|
|
},
|
|
"RuleOut": {
|
|
"properties": {
|
|
"enabled": {
|
|
"title": "Enabled",
|
|
"type": "boolean"
|
|
},
|
|
"id": {
|
|
"title": "Id",
|
|
"type": "integer"
|
|
},
|
|
"kind": {
|
|
"$ref": "#/components/schemas/RuleKind"
|
|
},
|
|
"last_matched_at": {
|
|
"anyOf": [
|
|
{
|
|
"format": "date-time",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Last Matched At"
|
|
},
|
|
"match_count": {
|
|
"title": "Match Count",
|
|
"type": "integer"
|
|
},
|
|
"match_type": {
|
|
"$ref": "#/components/schemas/RuleMatchType"
|
|
},
|
|
"note": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Note"
|
|
},
|
|
"pattern": {
|
|
"title": "Pattern",
|
|
"type": "string"
|
|
},
|
|
"priority": {
|
|
"title": "Priority",
|
|
"type": "integer"
|
|
},
|
|
"value": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Value"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"kind",
|
|
"match_type",
|
|
"pattern",
|
|
"value",
|
|
"note",
|
|
"enabled",
|
|
"priority",
|
|
"last_matched_at",
|
|
"match_count"
|
|
],
|
|
"title": "RuleOut",
|
|
"type": "object"
|
|
},
|
|
"RulePatch": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"enabled": {
|
|
"anyOf": [
|
|
{
|
|
"type": "boolean"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Enabled"
|
|
},
|
|
"kind": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/components/schemas/RuleKind"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
]
|
|
},
|
|
"match_type": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/components/schemas/RuleMatchType"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
]
|
|
},
|
|
"note": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Note"
|
|
},
|
|
"pattern": {
|
|
"anyOf": [
|
|
{
|
|
"maxLength": 512,
|
|
"minLength": 1,
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Pattern"
|
|
},
|
|
"priority": {
|
|
"anyOf": [
|
|
{
|
|
"type": "integer"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Priority"
|
|
},
|
|
"value": {
|
|
"anyOf": [
|
|
{
|
|
"maxLength": 512,
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Value"
|
|
}
|
|
},
|
|
"title": "RulePatch",
|
|
"type": "object"
|
|
},
|
|
"RunStatus": {
|
|
"enum": [
|
|
"running",
|
|
"ok",
|
|
"error"
|
|
],
|
|
"title": "RunStatus",
|
|
"type": "string"
|
|
},
|
|
"RunwayOut": {
|
|
"properties": {
|
|
"as_of": {
|
|
"format": "date",
|
|
"title": "As Of",
|
|
"type": "string"
|
|
},
|
|
"avg_baseline_3m_rub": {
|
|
"description": "decimal as string",
|
|
"title": "Avg Baseline 3M Rub",
|
|
"type": "string"
|
|
},
|
|
"liquid_reserve_rub": {
|
|
"description": "decimal as string",
|
|
"title": "Liquid Reserve Rub",
|
|
"type": "string"
|
|
},
|
|
"runway_months": {
|
|
"anyOf": [
|
|
{
|
|
"description": "decimal as string",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Runway Months"
|
|
}
|
|
},
|
|
"required": [
|
|
"as_of",
|
|
"liquid_reserve_rub",
|
|
"avg_baseline_3m_rub",
|
|
"runway_months"
|
|
],
|
|
"title": "RunwayOut",
|
|
"type": "object"
|
|
},
|
|
"SourceStatus": {
|
|
"properties": {
|
|
"cursor": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Cursor"
|
|
},
|
|
"last_run_at": {
|
|
"anyOf": [
|
|
{
|
|
"format": "date-time",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Last Run At"
|
|
},
|
|
"last_run_status": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/components/schemas/RunStatus"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
]
|
|
},
|
|
"last_success_at": {
|
|
"anyOf": [
|
|
{
|
|
"format": "date-time",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Last Success At"
|
|
},
|
|
"queued": {
|
|
"title": "Queued",
|
|
"type": "boolean"
|
|
},
|
|
"source": {
|
|
"title": "Source",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"source",
|
|
"cursor",
|
|
"last_run_at",
|
|
"last_success_at",
|
|
"last_run_status",
|
|
"queued"
|
|
],
|
|
"title": "SourceStatus",
|
|
"type": "object"
|
|
},
|
|
"SpendingRow": {
|
|
"properties": {
|
|
"amount_rub": {
|
|
"description": "decimal as string",
|
|
"title": "Amount Rub",
|
|
"type": "string"
|
|
},
|
|
"category_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "integer"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Category Id"
|
|
},
|
|
"category_name": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Category Name"
|
|
},
|
|
"month": {
|
|
"format": "date",
|
|
"title": "Month",
|
|
"type": "string"
|
|
},
|
|
"root_category_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "integer"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Root Category Id"
|
|
},
|
|
"root_category_name": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Root Category Name"
|
|
},
|
|
"txn_count": {
|
|
"title": "Txn Count",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"month",
|
|
"category_id",
|
|
"category_name",
|
|
"root_category_id",
|
|
"root_category_name",
|
|
"amount_rub",
|
|
"txn_count"
|
|
],
|
|
"title": "SpendingRow",
|
|
"type": "object"
|
|
},
|
|
"SyncJobOut": {
|
|
"properties": {
|
|
"id": {
|
|
"format": "uuid",
|
|
"title": "Id",
|
|
"type": "string"
|
|
},
|
|
"requested_at": {
|
|
"format": "date-time",
|
|
"title": "Requested At",
|
|
"type": "string"
|
|
},
|
|
"source": {
|
|
"title": "Source",
|
|
"type": "string"
|
|
},
|
|
"status": {
|
|
"$ref": "#/components/schemas/JobStatus"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"source",
|
|
"status",
|
|
"requested_at"
|
|
],
|
|
"title": "SyncJobOut",
|
|
"type": "object"
|
|
},
|
|
"SyncRunOut": {
|
|
"properties": {
|
|
"counts": {
|
|
"anyOf": [
|
|
{
|
|
"additionalProperties": true,
|
|
"type": "object"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Counts"
|
|
},
|
|
"cursor_after": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Cursor After"
|
|
},
|
|
"cursor_before": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Cursor Before"
|
|
},
|
|
"error": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Error"
|
|
},
|
|
"finished_at": {
|
|
"anyOf": [
|
|
{
|
|
"format": "date-time",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Finished At"
|
|
},
|
|
"id": {
|
|
"format": "uuid",
|
|
"title": "Id",
|
|
"type": "string"
|
|
},
|
|
"source": {
|
|
"title": "Source",
|
|
"type": "string"
|
|
},
|
|
"started_at": {
|
|
"format": "date-time",
|
|
"title": "Started At",
|
|
"type": "string"
|
|
},
|
|
"status": {
|
|
"$ref": "#/components/schemas/RunStatus"
|
|
},
|
|
"triggered_by": {
|
|
"title": "Triggered By",
|
|
"type": "string"
|
|
},
|
|
"warnings": {
|
|
"anyOf": [
|
|
{
|
|
"items": {},
|
|
"type": "array"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Warnings"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"source",
|
|
"status",
|
|
"triggered_by",
|
|
"started_at",
|
|
"finished_at",
|
|
"cursor_before",
|
|
"cursor_after",
|
|
"counts",
|
|
"warnings",
|
|
"error"
|
|
],
|
|
"title": "SyncRunOut",
|
|
"type": "object"
|
|
},
|
|
"TokenPair": {
|
|
"properties": {
|
|
"access_token": {
|
|
"title": "Access Token",
|
|
"type": "string"
|
|
},
|
|
"expires_in": {
|
|
"title": "Expires In",
|
|
"type": "integer"
|
|
},
|
|
"refresh_token": {
|
|
"title": "Refresh Token",
|
|
"type": "string"
|
|
},
|
|
"token_type": {
|
|
"default": "bearer",
|
|
"title": "Token Type",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"access_token",
|
|
"refresh_token",
|
|
"expires_in"
|
|
],
|
|
"title": "TokenPair",
|
|
"type": "object"
|
|
},
|
|
"TransactionOut": {
|
|
"properties": {
|
|
"category_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "integer"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Category Id"
|
|
},
|
|
"comment": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Comment"
|
|
},
|
|
"date": {
|
|
"format": "date",
|
|
"title": "Date",
|
|
"type": "string"
|
|
},
|
|
"deleted": {
|
|
"title": "Deleted",
|
|
"type": "boolean"
|
|
},
|
|
"flow_type": {
|
|
"$ref": "#/components/schemas/FlowType"
|
|
},
|
|
"hold": {
|
|
"title": "Hold",
|
|
"type": "boolean"
|
|
},
|
|
"id": {
|
|
"title": "Id",
|
|
"type": "integer"
|
|
},
|
|
"income": {
|
|
"description": "decimal as string",
|
|
"title": "Income",
|
|
"type": "string"
|
|
},
|
|
"income_account_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "integer"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Income Account Id"
|
|
},
|
|
"income_currency": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Income Currency"
|
|
},
|
|
"income_rub": {
|
|
"anyOf": [
|
|
{
|
|
"description": "decimal as string",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Income Rub"
|
|
},
|
|
"is_one_off": {
|
|
"title": "Is One Off",
|
|
"type": "boolean"
|
|
},
|
|
"mcc": {
|
|
"anyOf": [
|
|
{
|
|
"type": "integer"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Mcc"
|
|
},
|
|
"outcome": {
|
|
"description": "decimal as string",
|
|
"title": "Outcome",
|
|
"type": "string"
|
|
},
|
|
"outcome_account_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "integer"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Outcome Account Id"
|
|
},
|
|
"outcome_currency": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Outcome Currency"
|
|
},
|
|
"outcome_rub": {
|
|
"anyOf": [
|
|
{
|
|
"description": "decimal as string",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Outcome Rub"
|
|
},
|
|
"payee": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Payee"
|
|
},
|
|
"payee_canonical": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Payee Canonical"
|
|
},
|
|
"source_id": {
|
|
"title": "Source Id",
|
|
"type": "string"
|
|
},
|
|
"tags": {
|
|
"items": {
|
|
"type": "integer"
|
|
},
|
|
"title": "Tags",
|
|
"type": "array"
|
|
},
|
|
"trip_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "integer"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Trip Id"
|
|
},
|
|
"ts": {
|
|
"format": "date-time",
|
|
"title": "Ts",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"source_id",
|
|
"ts",
|
|
"date",
|
|
"income",
|
|
"income_currency",
|
|
"income_account_id",
|
|
"income_rub",
|
|
"outcome",
|
|
"outcome_currency",
|
|
"outcome_account_id",
|
|
"outcome_rub",
|
|
"payee",
|
|
"payee_canonical",
|
|
"comment",
|
|
"mcc",
|
|
"hold",
|
|
"deleted",
|
|
"flow_type",
|
|
"category_id",
|
|
"is_one_off",
|
|
"trip_id",
|
|
"tags"
|
|
],
|
|
"title": "TransactionOut",
|
|
"type": "object"
|
|
},
|
|
"TransactionPage": {
|
|
"properties": {
|
|
"items": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/TransactionOut"
|
|
},
|
|
"title": "Items",
|
|
"type": "array"
|
|
},
|
|
"page": {
|
|
"title": "Page",
|
|
"type": "integer"
|
|
},
|
|
"page_size": {
|
|
"title": "Page Size",
|
|
"type": "integer"
|
|
},
|
|
"total": {
|
|
"title": "Total",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"items",
|
|
"total",
|
|
"page",
|
|
"page_size"
|
|
],
|
|
"title": "TransactionPage",
|
|
"type": "object"
|
|
},
|
|
"UserOut": {
|
|
"properties": {
|
|
"email": {
|
|
"title": "Email",
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"title": "Id",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"email"
|
|
],
|
|
"title": "UserOut",
|
|
"type": "object"
|
|
}
|
|
},
|
|
"securitySchemes": {
|
|
"HTTPBearer": {
|
|
"scheme": "bearer",
|
|
"type": "http"
|
|
}
|
|
}
|
|
},
|
|
"info": {
|
|
"title": "fin-tracker",
|
|
"version": "0.1.0"
|
|
},
|
|
"openapi": "3.1.0",
|
|
"paths": {
|
|
"/api/v1/accounts": {
|
|
"get": {
|
|
"description": "Every account, archived ones included — the client decides what to show.",
|
|
"operationId": "accounts_list",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/AccountOut"
|
|
},
|
|
"title": "Response Accounts List",
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "List",
|
|
"tags": [
|
|
"accounts"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/accounts/{account_id}": {
|
|
"patch": {
|
|
"description": "Update the user-owned fields. Everything else is overwritten by the next sync.",
|
|
"operationId": "accounts_patch",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "account_id",
|
|
"required": true,
|
|
"schema": {
|
|
"title": "Account Id",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/AccountPatch"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/AccountOut"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Patch",
|
|
"tags": [
|
|
"accounts"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/auth/login": {
|
|
"post": {
|
|
"operationId": "auth_login",
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/LoginRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TokenPair"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"summary": "Login",
|
|
"tags": [
|
|
"auth"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/auth/logout": {
|
|
"post": {
|
|
"operationId": "auth_logout",
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/RefreshRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"204": {
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"summary": "Logout",
|
|
"tags": [
|
|
"auth"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/auth/me": {
|
|
"get": {
|
|
"operationId": "auth_me",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UserOut"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Me",
|
|
"tags": [
|
|
"auth"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/auth/refresh": {
|
|
"post": {
|
|
"operationId": "auth_refresh",
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/RefreshRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TokenPair"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"summary": "Refresh",
|
|
"tags": [
|
|
"auth"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/cashflow/monthly": {
|
|
"get": {
|
|
"description": "The last `months` months, oldest first.",
|
|
"operationId": "cashflow_monthly",
|
|
"parameters": [
|
|
{
|
|
"in": "query",
|
|
"name": "months",
|
|
"required": false,
|
|
"schema": {
|
|
"default": 12,
|
|
"maximum": 120,
|
|
"minimum": 1,
|
|
"title": "Months",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/CashFlowMonth"
|
|
},
|
|
"title": "Response Cashflow Monthly",
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Monthly",
|
|
"tags": [
|
|
"cashflow"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/categories": {
|
|
"get": {
|
|
"description": "Flat list of the ZenMoney tag tree; the client nests it by `parent_id`.",
|
|
"operationId": "categories_list",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/CategoryOut"
|
|
},
|
|
"title": "Response Categories List",
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "List",
|
|
"tags": [
|
|
"categories"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/data-quality": {
|
|
"get": {
|
|
"description": "Findings of the latest refresh, most serious first.",
|
|
"operationId": "metrics_data_quality",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/DataQualityRow"
|
|
},
|
|
"title": "Response Metrics Data Quality",
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Data Quality",
|
|
"tags": [
|
|
"metrics"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/health": {
|
|
"get": {
|
|
"operationId": "health_check",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Health"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"summary": "Check",
|
|
"tags": [
|
|
"health"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/metrics/refresh": {
|
|
"post": {
|
|
"description": "Rebuild every metric_* table inline (seconds at personal volumes).",
|
|
"operationId": "metrics_refresh",
|
|
"responses": {
|
|
"202": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/RefreshLogOut"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Refresh",
|
|
"tags": [
|
|
"metrics"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/metrics/status": {
|
|
"get": {
|
|
"description": "When the metric tables were last rebuilt, and whether it failed.",
|
|
"operationId": "metrics_status",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/components/schemas/RefreshLogOut"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Response Metrics Status"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Status",
|
|
"tags": [
|
|
"metrics"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/networth/breakdown": {
|
|
"get": {
|
|
"description": "The latest day's buckets, plus every account's current balance native and in RUB.",
|
|
"operationId": "networth_breakdown",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/NetWorthBreakdown"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Breakdown",
|
|
"tags": [
|
|
"networth"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/networth/series": {
|
|
"get": {
|
|
"description": "Daily net worth; defaults to the last 365 days.",
|
|
"operationId": "networth_series",
|
|
"parameters": [
|
|
{
|
|
"in": "query",
|
|
"name": "from",
|
|
"required": false,
|
|
"schema": {
|
|
"anyOf": [
|
|
{
|
|
"format": "date",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "From"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "to",
|
|
"required": false,
|
|
"schema": {
|
|
"anyOf": [
|
|
{
|
|
"format": "date",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "To"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/NetWorthDay"
|
|
},
|
|
"title": "Response Networth Series",
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Series",
|
|
"tags": [
|
|
"networth"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/rules": {
|
|
"get": {
|
|
"operationId": "rules_list",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/RuleOut"
|
|
},
|
|
"title": "Response Rules List",
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "List",
|
|
"tags": [
|
|
"rules"
|
|
]
|
|
},
|
|
"post": {
|
|
"operationId": "rules_create",
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/RuleCreate"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"201": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/RuleOut"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Create",
|
|
"tags": [
|
|
"rules"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/rules/apply": {
|
|
"post": {
|
|
"description": "Re-run the whole metric refresh so edited rules take effect everywhere at once.",
|
|
"operationId": "rules_apply",
|
|
"responses": {
|
|
"202": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/RefreshLogOut"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Apply",
|
|
"tags": [
|
|
"rules"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/rules/stale": {
|
|
"get": {
|
|
"description": "Enabled rules that matched nothing in the latest refresh: the payee was renamed,\nor the transaction was re-categorised in ZenMoney.",
|
|
"operationId": "rules_stale",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/RuleOut"
|
|
},
|
|
"title": "Response Rules Stale",
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Stale",
|
|
"tags": [
|
|
"rules"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/rules/{rule_id}": {
|
|
"delete": {
|
|
"operationId": "rules_delete",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "rule_id",
|
|
"required": true,
|
|
"schema": {
|
|
"title": "Rule Id",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"204": {
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Delete",
|
|
"tags": [
|
|
"rules"
|
|
]
|
|
},
|
|
"patch": {
|
|
"operationId": "rules_patch",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "rule_id",
|
|
"required": true,
|
|
"schema": {
|
|
"title": "Rule Id",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/RulePatch"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/RuleOut"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Patch",
|
|
"tags": [
|
|
"rules"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/runway": {
|
|
"get": {
|
|
"description": "How many months the liquid reserve covers; null before the first refresh.",
|
|
"operationId": "cashflow_runway",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/components/schemas/RunwayOut"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Response Cashflow Runway"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Runway",
|
|
"tags": [
|
|
"cashflow"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/spending/categories": {
|
|
"get": {
|
|
"description": "Expenses of one month by category, largest first.",
|
|
"operationId": "cashflow_spending",
|
|
"parameters": [
|
|
{
|
|
"description": "YYYY-MM; defaults to the latest month",
|
|
"in": "query",
|
|
"name": "month",
|
|
"required": false,
|
|
"schema": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "YYYY-MM; defaults to the latest month",
|
|
"title": "Month"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/SpendingRow"
|
|
},
|
|
"title": "Response Cashflow Spending",
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Spending",
|
|
"tags": [
|
|
"cashflow"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/sync/runs": {
|
|
"get": {
|
|
"operationId": "sync_runs",
|
|
"parameters": [
|
|
{
|
|
"in": "query",
|
|
"name": "source",
|
|
"required": false,
|
|
"schema": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Source"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "limit",
|
|
"required": false,
|
|
"schema": {
|
|
"default": 20,
|
|
"maximum": 200,
|
|
"minimum": 1,
|
|
"title": "Limit",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/SyncRunOut"
|
|
},
|
|
"title": "Response Sync Runs",
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Runs",
|
|
"tags": [
|
|
"sync"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/sync/status": {
|
|
"get": {
|
|
"operationId": "sync_status",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/SourceStatus"
|
|
},
|
|
"title": "Response Sync Status",
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Status",
|
|
"tags": [
|
|
"sync"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/sync/{source}": {
|
|
"post": {
|
|
"operationId": "sync_trigger",
|
|
"parameters": [
|
|
{
|
|
"in": "path",
|
|
"name": "source",
|
|
"required": true,
|
|
"schema": {
|
|
"title": "Source",
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"202": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/SyncJobOut"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "Trigger",
|
|
"tags": [
|
|
"sync"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/transactions": {
|
|
"get": {
|
|
"description": "One page of transactions, newest first, with RUB amounts at each own date's rate.",
|
|
"operationId": "transactions_list",
|
|
"parameters": [
|
|
{
|
|
"in": "query",
|
|
"name": "from",
|
|
"required": false,
|
|
"schema": {
|
|
"anyOf": [
|
|
{
|
|
"format": "date",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "From"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "to",
|
|
"required": false,
|
|
"schema": {
|
|
"anyOf": [
|
|
{
|
|
"format": "date",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "To"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "account_id",
|
|
"required": false,
|
|
"schema": {
|
|
"anyOf": [
|
|
{
|
|
"type": "integer"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Account Id"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "category_id",
|
|
"required": false,
|
|
"schema": {
|
|
"anyOf": [
|
|
{
|
|
"type": "integer"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Category Id"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "flow_type",
|
|
"required": false,
|
|
"schema": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/components/schemas/FlowType"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"title": "Flow Type"
|
|
}
|
|
},
|
|
{
|
|
"description": "substring of payee or comment",
|
|
"in": "query",
|
|
"name": "q",
|
|
"required": false,
|
|
"schema": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "substring of payee or comment",
|
|
"title": "Q"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "include_deleted",
|
|
"required": false,
|
|
"schema": {
|
|
"default": false,
|
|
"title": "Include Deleted",
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "page",
|
|
"required": false,
|
|
"schema": {
|
|
"default": 1,
|
|
"minimum": 1,
|
|
"title": "Page",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
{
|
|
"in": "query",
|
|
"name": "page_size",
|
|
"required": false,
|
|
"schema": {
|
|
"default": 50,
|
|
"maximum": 500,
|
|
"minimum": 1,
|
|
"title": "Page Size",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TransactionPage"
|
|
}
|
|
}
|
|
},
|
|
"description": "Successful Response"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/problem+json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Problem"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"HTTPBearer": []
|
|
}
|
|
],
|
|
"summary": "List",
|
|
"tags": [
|
|
"transactions"
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"servers": [
|
|
{
|
|
"url": "/"
|
|
}
|
|
]
|
|
}
|