mirror of
https://github.com/we-promise/sure.git
synced 2026-04-07 14:31:25 +00:00
* feat: add valuations API endpoints for managing account reconciliations * refactor: formatting * fix: make account extraction clearer * feat: validation and error handling improvements * feat: transaction * feat: error handling * Add API documentation LLM context * Make it easier for people * feat: transaction in creation * feat: add OpenAPI spec for Valuations API * fix: update notes validation to check for key presence * Prevent double render * All other docs use `apiKeyAuth` * More `apiKeyAuth` * Remove testing assertions from API doc specs * fix: correct valuation entry references --------- Signed-off-by: Juan José Mata <juanjo.mata@gmail.com> Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
1763 lines
44 KiB
YAML
1763 lines
44 KiB
YAML
---
|
|
openapi: 3.0.3
|
|
info:
|
|
title: Sure API
|
|
version: v1
|
|
description: OpenAPI documentation generated from executable request specs.
|
|
servers:
|
|
- url: https://app.sure.am
|
|
description: Production
|
|
- url: http://localhost:3000
|
|
description: Local development
|
|
components:
|
|
securitySchemes:
|
|
apiKeyAuth:
|
|
type: apiKey
|
|
name: X-Api-Key
|
|
in: header
|
|
description: API key for authentication. Generate one from your account settings.
|
|
schemas:
|
|
Pagination:
|
|
type: object
|
|
required:
|
|
- page
|
|
- per_page
|
|
- total_count
|
|
- total_pages
|
|
properties:
|
|
page:
|
|
type: integer
|
|
minimum: 1
|
|
per_page:
|
|
type: integer
|
|
minimum: 1
|
|
total_count:
|
|
type: integer
|
|
minimum: 0
|
|
total_pages:
|
|
type: integer
|
|
minimum: 0
|
|
ErrorResponse:
|
|
type: object
|
|
required:
|
|
- error
|
|
properties:
|
|
error:
|
|
type: string
|
|
message:
|
|
type: string
|
|
nullable: true
|
|
details:
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: string
|
|
- type: object
|
|
nullable: true
|
|
ToolCall:
|
|
type: object
|
|
required:
|
|
- id
|
|
- function_name
|
|
- function_arguments
|
|
- created_at
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
function_name:
|
|
type: string
|
|
function_arguments:
|
|
type: object
|
|
additionalProperties: true
|
|
function_result:
|
|
type: object
|
|
additionalProperties: true
|
|
nullable: true
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
Message:
|
|
type: object
|
|
required:
|
|
- id
|
|
- type
|
|
- role
|
|
- content
|
|
- created_at
|
|
- updated_at
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
type:
|
|
type: string
|
|
enum:
|
|
- user_message
|
|
- assistant_message
|
|
role:
|
|
type: string
|
|
enum:
|
|
- user
|
|
- assistant
|
|
content:
|
|
type: string
|
|
model:
|
|
type: string
|
|
nullable: true
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
tool_calls:
|
|
type: array
|
|
items:
|
|
"$ref": "#/components/schemas/ToolCall"
|
|
nullable: true
|
|
MessageResponse:
|
|
allOf:
|
|
- "$ref": "#/components/schemas/Message"
|
|
- type: object
|
|
required:
|
|
- chat_id
|
|
properties:
|
|
chat_id:
|
|
type: string
|
|
format: uuid
|
|
ai_response_status:
|
|
type: string
|
|
enum:
|
|
- pending
|
|
- complete
|
|
- failed
|
|
nullable: true
|
|
ai_response_message:
|
|
type: string
|
|
nullable: true
|
|
ChatResource:
|
|
type: object
|
|
required:
|
|
- id
|
|
- title
|
|
- created_at
|
|
- updated_at
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
title:
|
|
type: string
|
|
error:
|
|
type: string
|
|
nullable: true
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
ChatSummary:
|
|
allOf:
|
|
- "$ref": "#/components/schemas/ChatResource"
|
|
- type: object
|
|
required:
|
|
- message_count
|
|
properties:
|
|
message_count:
|
|
type: integer
|
|
minimum: 0
|
|
last_message_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
ChatDetail:
|
|
allOf:
|
|
- "$ref": "#/components/schemas/ChatResource"
|
|
- type: object
|
|
required:
|
|
- messages
|
|
properties:
|
|
messages:
|
|
type: array
|
|
items:
|
|
"$ref": "#/components/schemas/Message"
|
|
pagination:
|
|
"$ref": "#/components/schemas/Pagination"
|
|
nullable: true
|
|
ChatCollection:
|
|
type: object
|
|
required:
|
|
- chats
|
|
- pagination
|
|
properties:
|
|
chats:
|
|
type: array
|
|
items:
|
|
"$ref": "#/components/schemas/ChatSummary"
|
|
pagination:
|
|
"$ref": "#/components/schemas/Pagination"
|
|
RetryResponse:
|
|
type: object
|
|
required:
|
|
- message
|
|
- message_id
|
|
properties:
|
|
message:
|
|
type: string
|
|
message_id:
|
|
type: string
|
|
format: uuid
|
|
Account:
|
|
type: object
|
|
required:
|
|
- id
|
|
- name
|
|
- account_type
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
name:
|
|
type: string
|
|
account_type:
|
|
type: string
|
|
AccountDetail:
|
|
type: object
|
|
required:
|
|
- id
|
|
- name
|
|
- balance
|
|
- currency
|
|
- classification
|
|
- account_type
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
name:
|
|
type: string
|
|
balance:
|
|
type: string
|
|
currency:
|
|
type: string
|
|
classification:
|
|
type: string
|
|
account_type:
|
|
type: string
|
|
AccountCollection:
|
|
type: object
|
|
required:
|
|
- accounts
|
|
- pagination
|
|
properties:
|
|
accounts:
|
|
type: array
|
|
items:
|
|
"$ref": "#/components/schemas/AccountDetail"
|
|
pagination:
|
|
"$ref": "#/components/schemas/Pagination"
|
|
Category:
|
|
type: object
|
|
required:
|
|
- id
|
|
- name
|
|
- classification
|
|
- color
|
|
- icon
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
name:
|
|
type: string
|
|
classification:
|
|
type: string
|
|
color:
|
|
type: string
|
|
icon:
|
|
type: string
|
|
CategoryParent:
|
|
type: object
|
|
required:
|
|
- id
|
|
- name
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
name:
|
|
type: string
|
|
CategoryDetail:
|
|
type: object
|
|
required:
|
|
- id
|
|
- name
|
|
- classification
|
|
- color
|
|
- icon
|
|
- subcategories_count
|
|
- created_at
|
|
- updated_at
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
name:
|
|
type: string
|
|
classification:
|
|
type: string
|
|
enum:
|
|
- income
|
|
- expense
|
|
color:
|
|
type: string
|
|
icon:
|
|
type: string
|
|
parent:
|
|
"$ref": "#/components/schemas/CategoryParent"
|
|
nullable: true
|
|
subcategories_count:
|
|
type: integer
|
|
minimum: 0
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
CategoryCollection:
|
|
type: object
|
|
required:
|
|
- categories
|
|
- pagination
|
|
properties:
|
|
categories:
|
|
type: array
|
|
items:
|
|
"$ref": "#/components/schemas/CategoryDetail"
|
|
pagination:
|
|
"$ref": "#/components/schemas/Pagination"
|
|
Merchant:
|
|
type: object
|
|
required:
|
|
- id
|
|
- name
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
name:
|
|
type: string
|
|
Tag:
|
|
type: object
|
|
required:
|
|
- id
|
|
- name
|
|
- color
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
name:
|
|
type: string
|
|
color:
|
|
type: string
|
|
TagDetail:
|
|
type: object
|
|
required:
|
|
- id
|
|
- name
|
|
- color
|
|
- created_at
|
|
- updated_at
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
name:
|
|
type: string
|
|
color:
|
|
type: string
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
TagCollection:
|
|
type: array
|
|
items:
|
|
"$ref": "#/components/schemas/TagDetail"
|
|
Transfer:
|
|
type: object
|
|
required:
|
|
- id
|
|
- amount
|
|
- currency
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
amount:
|
|
type: string
|
|
currency:
|
|
type: string
|
|
other_account:
|
|
"$ref": "#/components/schemas/Account"
|
|
nullable: true
|
|
Transaction:
|
|
type: object
|
|
required:
|
|
- id
|
|
- date
|
|
- amount
|
|
- currency
|
|
- name
|
|
- classification
|
|
- account
|
|
- tags
|
|
- created_at
|
|
- updated_at
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
date:
|
|
type: string
|
|
format: date
|
|
amount:
|
|
type: string
|
|
currency:
|
|
type: string
|
|
name:
|
|
type: string
|
|
notes:
|
|
type: string
|
|
nullable: true
|
|
classification:
|
|
type: string
|
|
account:
|
|
"$ref": "#/components/schemas/Account"
|
|
category:
|
|
"$ref": "#/components/schemas/Category"
|
|
nullable: true
|
|
merchant:
|
|
"$ref": "#/components/schemas/Merchant"
|
|
nullable: true
|
|
tags:
|
|
type: array
|
|
items:
|
|
"$ref": "#/components/schemas/Tag"
|
|
transfer:
|
|
"$ref": "#/components/schemas/Transfer"
|
|
nullable: true
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
TransactionCollection:
|
|
type: object
|
|
required:
|
|
- transactions
|
|
- pagination
|
|
properties:
|
|
transactions:
|
|
type: array
|
|
items:
|
|
"$ref": "#/components/schemas/Transaction"
|
|
pagination:
|
|
"$ref": "#/components/schemas/Pagination"
|
|
Valuation:
|
|
type: object
|
|
required:
|
|
- id
|
|
- date
|
|
- amount
|
|
- currency
|
|
- kind
|
|
- account
|
|
- created_at
|
|
- updated_at
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
description: Entry ID for the valuation
|
|
date:
|
|
type: string
|
|
format: date
|
|
amount:
|
|
type: string
|
|
currency:
|
|
type: string
|
|
notes:
|
|
type: string
|
|
nullable: true
|
|
kind:
|
|
type: string
|
|
account:
|
|
"$ref": "#/components/schemas/Account"
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
DeleteResponse:
|
|
type: object
|
|
required:
|
|
- message
|
|
properties:
|
|
message:
|
|
type: string
|
|
ImportConfiguration:
|
|
type: object
|
|
properties:
|
|
date_col_label:
|
|
type: string
|
|
nullable: true
|
|
amount_col_label:
|
|
type: string
|
|
nullable: true
|
|
name_col_label:
|
|
type: string
|
|
nullable: true
|
|
category_col_label:
|
|
type: string
|
|
nullable: true
|
|
tags_col_label:
|
|
type: string
|
|
nullable: true
|
|
notes_col_label:
|
|
type: string
|
|
nullable: true
|
|
account_col_label:
|
|
type: string
|
|
nullable: true
|
|
date_format:
|
|
type: string
|
|
nullable: true
|
|
number_format:
|
|
type: string
|
|
nullable: true
|
|
signage_convention:
|
|
type: string
|
|
nullable: true
|
|
ImportStats:
|
|
type: object
|
|
properties:
|
|
rows_count:
|
|
type: integer
|
|
minimum: 0
|
|
valid_rows_count:
|
|
type: integer
|
|
minimum: 0
|
|
nullable: true
|
|
ImportSummary:
|
|
type: object
|
|
required:
|
|
- id
|
|
- type
|
|
- status
|
|
- created_at
|
|
- updated_at
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
type:
|
|
type: string
|
|
enum:
|
|
- TransactionImport
|
|
- TradeImport
|
|
- AccountImport
|
|
- MintImport
|
|
- CategoryImport
|
|
- RuleImport
|
|
status:
|
|
type: string
|
|
enum:
|
|
- pending
|
|
- complete
|
|
- importing
|
|
- reverting
|
|
- revert_failed
|
|
- failed
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
account_id:
|
|
type: string
|
|
format: uuid
|
|
nullable: true
|
|
rows_count:
|
|
type: integer
|
|
minimum: 0
|
|
error:
|
|
type: string
|
|
nullable: true
|
|
ImportDetail:
|
|
type: object
|
|
required:
|
|
- id
|
|
- type
|
|
- status
|
|
- created_at
|
|
- updated_at
|
|
properties:
|
|
id:
|
|
type: string
|
|
format: uuid
|
|
type:
|
|
type: string
|
|
enum:
|
|
- TransactionImport
|
|
- TradeImport
|
|
- AccountImport
|
|
- MintImport
|
|
- CategoryImport
|
|
- RuleImport
|
|
status:
|
|
type: string
|
|
enum:
|
|
- pending
|
|
- complete
|
|
- importing
|
|
- reverting
|
|
- revert_failed
|
|
- failed
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
account_id:
|
|
type: string
|
|
format: uuid
|
|
nullable: true
|
|
error:
|
|
type: string
|
|
nullable: true
|
|
configuration:
|
|
"$ref": "#/components/schemas/ImportConfiguration"
|
|
stats:
|
|
"$ref": "#/components/schemas/ImportStats"
|
|
ImportCollection:
|
|
type: object
|
|
required:
|
|
- data
|
|
- meta
|
|
properties:
|
|
data:
|
|
type: array
|
|
items:
|
|
"$ref": "#/components/schemas/ImportSummary"
|
|
meta:
|
|
type: object
|
|
required:
|
|
- current_page
|
|
- total_pages
|
|
- total_count
|
|
- per_page
|
|
properties:
|
|
current_page:
|
|
type: integer
|
|
minimum: 1
|
|
next_page:
|
|
type: integer
|
|
nullable: true
|
|
prev_page:
|
|
type: integer
|
|
nullable: true
|
|
total_pages:
|
|
type: integer
|
|
minimum: 0
|
|
total_count:
|
|
type: integer
|
|
minimum: 0
|
|
per_page:
|
|
type: integer
|
|
minimum: 1
|
|
ImportResponse:
|
|
type: object
|
|
required:
|
|
- data
|
|
properties:
|
|
data:
|
|
"$ref": "#/components/schemas/ImportDetail"
|
|
paths:
|
|
"/api/v1/accounts":
|
|
get:
|
|
summary: List accounts
|
|
tags:
|
|
- Accounts
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters:
|
|
- name: page
|
|
in: query
|
|
required: false
|
|
description: 'Page number (default: 1)'
|
|
schema:
|
|
type: integer
|
|
- name: per_page
|
|
in: query
|
|
required: false
|
|
description: 'Items per page (default: 25, max: 100)'
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: accounts paginated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/AccountCollection"
|
|
"/api/v1/categories":
|
|
get:
|
|
summary: List categories
|
|
tags:
|
|
- Categories
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters:
|
|
- name: page
|
|
in: query
|
|
required: false
|
|
description: 'Page number (default: 1)'
|
|
schema:
|
|
type: integer
|
|
- name: per_page
|
|
in: query
|
|
required: false
|
|
description: 'Items per page (default: 25, max: 100)'
|
|
schema:
|
|
type: integer
|
|
- name: classification
|
|
in: query
|
|
required: false
|
|
description: Filter by classification (income or expense)
|
|
schema:
|
|
type: string
|
|
enum:
|
|
- income
|
|
- expense
|
|
- name: roots_only
|
|
in: query
|
|
required: false
|
|
description: Return only root categories (no parent)
|
|
schema:
|
|
type: boolean
|
|
- name: parent_id
|
|
in: query
|
|
required: false
|
|
description: Filter by parent category ID
|
|
schema:
|
|
type: string
|
|
format: uuid
|
|
responses:
|
|
'200':
|
|
description: categories filtered by parent
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/CategoryCollection"
|
|
"/api/v1/categories/{id}":
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Category ID
|
|
schema:
|
|
type: string
|
|
get:
|
|
summary: Retrieve a category
|
|
tags:
|
|
- Categories
|
|
security:
|
|
- apiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: subcategory retrieved with parent
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/CategoryDetail"
|
|
'404':
|
|
description: category not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
"/api/v1/chats":
|
|
get:
|
|
summary: List chats
|
|
tags:
|
|
- Chats
|
|
security:
|
|
- apiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: chats listed
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ChatCollection"
|
|
'403':
|
|
description: AI features disabled
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
post:
|
|
summary: Create chat
|
|
tags:
|
|
- Chats
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters: []
|
|
responses:
|
|
'201':
|
|
description: chat created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ChatDetail"
|
|
'422':
|
|
description: validation error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
title:
|
|
type: string
|
|
example: Monthly budget review
|
|
message:
|
|
type: string
|
|
description: Optional initial message in the chat
|
|
model:
|
|
type: string
|
|
description: Optional OpenAI model identifier
|
|
required:
|
|
- title
|
|
required: true
|
|
"/api/v1/chats/{id}":
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Chat ID
|
|
schema:
|
|
type: string
|
|
get:
|
|
summary: Retrieve a chat
|
|
tags:
|
|
- Chats
|
|
security:
|
|
- apiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: chat retrieved
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ChatDetail"
|
|
'404':
|
|
description: chat not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
patch:
|
|
summary: Update a chat
|
|
tags:
|
|
- Chats
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters: []
|
|
responses:
|
|
'200':
|
|
description: chat updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ChatDetail"
|
|
'404':
|
|
description: chat not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
'422':
|
|
description: validation error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
title:
|
|
type: string
|
|
example: Updated chat title
|
|
required: true
|
|
delete:
|
|
summary: Delete a chat
|
|
tags:
|
|
- Chats
|
|
security:
|
|
- apiKeyAuth: []
|
|
responses:
|
|
'204':
|
|
description: chat deleted
|
|
'404':
|
|
description: chat not found
|
|
"/api/v1/chats/{chat_id}/messages":
|
|
parameters:
|
|
- name: chat_id
|
|
in: path
|
|
required: true
|
|
description: Chat ID
|
|
schema:
|
|
type: string
|
|
post:
|
|
summary: Create a message
|
|
tags:
|
|
- Chat Messages
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters: []
|
|
responses:
|
|
'201':
|
|
description: message created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/MessageResponse"
|
|
'404':
|
|
description: chat not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
'422':
|
|
description: validation error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
content:
|
|
type: string
|
|
model:
|
|
type: string
|
|
required:
|
|
- content
|
|
required: true
|
|
"/api/v1/chats/{chat_id}/messages/retry":
|
|
parameters:
|
|
- name: chat_id
|
|
in: path
|
|
required: true
|
|
description: Chat ID
|
|
schema:
|
|
type: string
|
|
post:
|
|
summary: Retry the last assistant response
|
|
tags:
|
|
- Chat Messages
|
|
security:
|
|
- apiKeyAuth: []
|
|
responses:
|
|
'202':
|
|
description: retry started
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/RetryResponse"
|
|
'404':
|
|
description: chat not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
'422':
|
|
description: no assistant message available
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
"/api/v1/imports":
|
|
get:
|
|
summary: List imports
|
|
description: List all imports for the user's family with pagination and filtering.
|
|
tags:
|
|
- Imports
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters:
|
|
- name: page
|
|
in: query
|
|
required: false
|
|
description: 'Page number (default: 1)'
|
|
schema:
|
|
type: integer
|
|
- name: per_page
|
|
in: query
|
|
required: false
|
|
description: 'Items per page (default: 25, max: 100)'
|
|
schema:
|
|
type: integer
|
|
- name: status
|
|
in: query
|
|
required: false
|
|
description: Filter by status
|
|
schema:
|
|
type: string
|
|
enum:
|
|
- pending
|
|
- complete
|
|
- importing
|
|
- reverting
|
|
- revert_failed
|
|
- failed
|
|
- name: type
|
|
in: query
|
|
required: false
|
|
description: Filter by import type
|
|
schema:
|
|
type: string
|
|
enum:
|
|
- TransactionImport
|
|
- TradeImport
|
|
- AccountImport
|
|
- MintImport
|
|
- CategoryImport
|
|
- RuleImport
|
|
responses:
|
|
'200':
|
|
description: imports filtered by type
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ImportCollection"
|
|
post:
|
|
summary: Create import
|
|
description: Create a new import from raw CSV content.
|
|
tags:
|
|
- Imports
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters: []
|
|
responses:
|
|
'201':
|
|
description: import created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ImportResponse"
|
|
'422':
|
|
description: validation error - file too large
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
raw_file_content:
|
|
type: string
|
|
description: The raw CSV content as a string
|
|
type:
|
|
type: string
|
|
enum:
|
|
- TransactionImport
|
|
- TradeImport
|
|
- AccountImport
|
|
- MintImport
|
|
- CategoryImport
|
|
- RuleImport
|
|
description: Import type (defaults to TransactionImport)
|
|
account_id:
|
|
type: string
|
|
format: uuid
|
|
description: Account ID to import into
|
|
publish:
|
|
type: string
|
|
description: Set to "true" to automatically queue for processing
|
|
if configuration is valid
|
|
date_col_label:
|
|
type: string
|
|
description: Header name for the date column
|
|
amount_col_label:
|
|
type: string
|
|
description: Header name for the amount column
|
|
name_col_label:
|
|
type: string
|
|
description: Header name for the transaction name column
|
|
category_col_label:
|
|
type: string
|
|
description: Header name for the category column
|
|
tags_col_label:
|
|
type: string
|
|
description: Header name for the tags column
|
|
notes_col_label:
|
|
type: string
|
|
description: Header name for the notes column
|
|
date_format:
|
|
type: string
|
|
description: Date format pattern (e.g., "%m/%d/%Y")
|
|
number_format:
|
|
type: string
|
|
enum:
|
|
- '1,234.56'
|
|
- 1.234,56
|
|
- 1 234,56
|
|
- '1,234'
|
|
description: Number format for parsing amounts
|
|
signage_convention:
|
|
type: string
|
|
enum:
|
|
- inflows_positive
|
|
- inflows_negative
|
|
description: How to interpret positive/negative amounts
|
|
col_sep:
|
|
type: string
|
|
enum:
|
|
- ","
|
|
- ";"
|
|
description: Column separator
|
|
required: true
|
|
"/api/v1/imports/{id}":
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Import ID
|
|
schema:
|
|
type: string
|
|
get:
|
|
summary: Retrieve an import
|
|
description: Retrieve detailed information about a specific import, including
|
|
configuration and row statistics.
|
|
tags:
|
|
- Imports
|
|
security:
|
|
- apiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: import retrieved
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ImportResponse"
|
|
'404':
|
|
description: import not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
"/api/v1/tags":
|
|
get:
|
|
summary: List tags
|
|
tags:
|
|
- Tags
|
|
security:
|
|
- apiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: tags listed
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/TagCollection"
|
|
post:
|
|
summary: Create tag
|
|
tags:
|
|
- Tags
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters: []
|
|
responses:
|
|
'201':
|
|
description: tag created with auto-assigned color
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/TagDetail"
|
|
'422':
|
|
description: validation error - missing name
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
tag:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
description: Tag name (required)
|
|
color:
|
|
type: string
|
|
description: Hex color code (optional, auto-assigned if not
|
|
provided)
|
|
required:
|
|
- name
|
|
required:
|
|
- tag
|
|
required: true
|
|
"/api/v1/tags/{id}":
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Tag ID
|
|
schema:
|
|
type: string
|
|
get:
|
|
summary: Retrieve a tag
|
|
tags:
|
|
- Tags
|
|
security:
|
|
- apiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: tag retrieved
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/TagDetail"
|
|
'404':
|
|
description: tag not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
patch:
|
|
summary: Update a tag
|
|
tags:
|
|
- Tags
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters: []
|
|
responses:
|
|
'200':
|
|
description: tag updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/TagDetail"
|
|
'404':
|
|
description: tag not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
tag:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
color:
|
|
type: string
|
|
required: true
|
|
delete:
|
|
summary: Delete a tag
|
|
tags:
|
|
- Tags
|
|
security:
|
|
- apiKeyAuth: []
|
|
responses:
|
|
'204':
|
|
description: tag deleted
|
|
'404':
|
|
description: tag not found
|
|
"/api/v1/transactions":
|
|
get:
|
|
summary: List transactions
|
|
tags:
|
|
- Transactions
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters:
|
|
- name: page
|
|
in: query
|
|
required: false
|
|
description: 'Page number (default: 1)'
|
|
schema:
|
|
type: integer
|
|
- name: per_page
|
|
in: query
|
|
required: false
|
|
description: 'Items per page (default: 25, max: 100)'
|
|
schema:
|
|
type: integer
|
|
- name: account_id
|
|
in: query
|
|
required: false
|
|
description: Filter by account ID
|
|
schema:
|
|
type: string
|
|
- name: category_id
|
|
in: query
|
|
required: false
|
|
description: Filter by category ID
|
|
schema:
|
|
type: string
|
|
- name: merchant_id
|
|
in: query
|
|
required: false
|
|
description: Filter by merchant ID
|
|
schema:
|
|
type: string
|
|
- name: start_date
|
|
in: query
|
|
required: false
|
|
description: Filter transactions from this date
|
|
schema:
|
|
type: string
|
|
format: date
|
|
- name: end_date
|
|
in: query
|
|
required: false
|
|
description: Filter transactions until this date
|
|
schema:
|
|
type: string
|
|
format: date
|
|
- name: min_amount
|
|
in: query
|
|
required: false
|
|
description: Filter by minimum amount
|
|
schema:
|
|
type: number
|
|
- name: max_amount
|
|
in: query
|
|
required: false
|
|
description: Filter by maximum amount
|
|
schema:
|
|
type: number
|
|
- name: type
|
|
in: query
|
|
required: false
|
|
description: Filter by transaction type
|
|
schema:
|
|
type: string
|
|
enum:
|
|
- income
|
|
- expense
|
|
- name: search
|
|
in: query
|
|
required: false
|
|
description: Search by name, notes, or merchant name
|
|
schema:
|
|
type: string
|
|
- name: account_ids
|
|
in: query
|
|
required: false
|
|
description: Filter by multiple account IDs
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: string
|
|
- name: category_ids
|
|
in: query
|
|
required: false
|
|
description: Filter by multiple category IDs
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: string
|
|
- name: merchant_ids
|
|
in: query
|
|
required: false
|
|
description: Filter by multiple merchant IDs
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: string
|
|
- name: tag_ids
|
|
in: query
|
|
required: false
|
|
description: Filter by tag IDs
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: transactions filtered by date range
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/TransactionCollection"
|
|
post:
|
|
summary: Create transaction
|
|
tags:
|
|
- Transactions
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters: []
|
|
responses:
|
|
'201':
|
|
description: transaction created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/Transaction"
|
|
'422':
|
|
description: validation error - missing required fields
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
transaction:
|
|
type: object
|
|
properties:
|
|
account_id:
|
|
type: string
|
|
format: uuid
|
|
description: Account ID (required)
|
|
date:
|
|
type: string
|
|
format: date
|
|
description: Transaction date
|
|
amount:
|
|
type: number
|
|
description: Transaction amount
|
|
name:
|
|
type: string
|
|
description: Transaction name/description
|
|
description:
|
|
type: string
|
|
description: Alternative to name field
|
|
notes:
|
|
type: string
|
|
description: Additional notes
|
|
currency:
|
|
type: string
|
|
description: Currency code (defaults to family currency)
|
|
category_id:
|
|
type: string
|
|
format: uuid
|
|
description: Category ID
|
|
merchant_id:
|
|
type: string
|
|
format: uuid
|
|
description: Merchant ID
|
|
nature:
|
|
type: string
|
|
enum:
|
|
- income
|
|
- expense
|
|
- inflow
|
|
- outflow
|
|
description: Transaction nature (determines sign)
|
|
tag_ids:
|
|
type: array
|
|
items:
|
|
type: string
|
|
format: uuid
|
|
description: Array of tag IDs
|
|
required:
|
|
- account_id
|
|
- date
|
|
- amount
|
|
- name
|
|
required:
|
|
- transaction
|
|
required: true
|
|
"/api/v1/transactions/{id}":
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Transaction ID
|
|
schema:
|
|
type: string
|
|
get:
|
|
summary: Retrieve a transaction
|
|
tags:
|
|
- Transactions
|
|
security:
|
|
- apiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: transaction retrieved
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/Transaction"
|
|
'404':
|
|
description: transaction not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
patch:
|
|
summary: Update a transaction
|
|
tags:
|
|
- Transactions
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters: []
|
|
responses:
|
|
'200':
|
|
description: transaction updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/Transaction"
|
|
'404':
|
|
description: transaction not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
transaction:
|
|
type: object
|
|
properties:
|
|
date:
|
|
type: string
|
|
format: date
|
|
amount:
|
|
type: number
|
|
name:
|
|
type: string
|
|
description:
|
|
type: string
|
|
description: Alternative to name field
|
|
notes:
|
|
type: string
|
|
currency:
|
|
type: string
|
|
description: Currency code
|
|
category_id:
|
|
type: string
|
|
format: uuid
|
|
merchant_id:
|
|
type: string
|
|
format: uuid
|
|
nature:
|
|
type: string
|
|
enum:
|
|
- income
|
|
- expense
|
|
- inflow
|
|
- outflow
|
|
tag_ids:
|
|
type: array
|
|
items:
|
|
type: string
|
|
format: uuid
|
|
required: true
|
|
delete:
|
|
summary: Delete a transaction
|
|
tags:
|
|
- Transactions
|
|
security:
|
|
- apiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: transaction deleted
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/DeleteResponse"
|
|
'404':
|
|
description: transaction not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
"/api/v1/valuations":
|
|
post:
|
|
summary: Create valuation
|
|
tags:
|
|
- Valuations
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters:
|
|
- name: Authorization
|
|
in: header
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Bearer token with write scope
|
|
responses:
|
|
'201':
|
|
description: valuation created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/Valuation"
|
|
'422':
|
|
description: validation error - missing date
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
'404':
|
|
description: account not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
valuation:
|
|
type: object
|
|
properties:
|
|
account_id:
|
|
type: string
|
|
format: uuid
|
|
description: Account ID (required)
|
|
amount:
|
|
type: number
|
|
description: Valuation amount (required)
|
|
date:
|
|
type: string
|
|
format: date
|
|
description: Valuation date (required)
|
|
notes:
|
|
type: string
|
|
description: Additional notes
|
|
required:
|
|
- account_id
|
|
- amount
|
|
- date
|
|
required:
|
|
- valuation
|
|
required: true
|
|
"/api/v1/valuations/{id}":
|
|
parameters:
|
|
- name: Authorization
|
|
in: header
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Bearer token
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Valuation ID (entry ID)
|
|
schema:
|
|
type: string
|
|
get:
|
|
summary: Retrieve a valuation
|
|
tags:
|
|
- Valuations
|
|
security:
|
|
- apiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: valuation retrieved
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/Valuation"
|
|
'404':
|
|
description: valuation not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
patch:
|
|
summary: Update a valuation
|
|
tags:
|
|
- Valuations
|
|
security:
|
|
- apiKeyAuth: []
|
|
parameters: []
|
|
responses:
|
|
'200':
|
|
description: valuation updated with amount and date
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/Valuation"
|
|
'422':
|
|
description: validation error - only one of amount/date provided
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
'404':
|
|
description: valuation not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
valuation:
|
|
type: object
|
|
properties:
|
|
amount:
|
|
type: number
|
|
description: New valuation amount (must provide with date)
|
|
date:
|
|
type: string
|
|
format: date
|
|
description: New valuation date (must provide with amount)
|
|
notes:
|
|
type: string
|
|
description: Additional notes
|
|
required: true
|