{"openapi":"3.1.0","info":{"title":"Money Manager API","version":"1.0.0","description":"REST API for personal & team finance tracking. Designed for both browsers (Clerk session) and machine clients (API keys with scopes). All mutating endpoints accept an `Idempotency-Key` header.","contact":{"name":"Money Manager"}},"servers":[{"url":"https://app.moneymanager.example/api","description":"Production"}],"components":{"securitySchemes":{"apiKey":{"type":"apiKey","in":"header","name":"x-api-key"},"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API key"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{},"requestId":{"type":"string"}},"required":["code","message"]}},"required":["error"]}},"responses":{"BadRequest":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Missing or invalid auth","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"Insufficient role or scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Internal":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/wallets":{"get":{"summary":"List wallets in the active workspace","tags":["wallets"],"operationId":"listWallets","security":[{"apiKey":[]},{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}},"post":{"summary":"Create a wallet","tags":["wallets"],"operationId":"postWallets","security":[{"apiKey":[]},{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":50},"description":{"type":"string","maxLength":255},"type":{"type":"string","enum":["cash","card","bank_account","digital_wallet"],"default":"cash"},"currency":{"type":"string","default":"MXN"},"cardColor":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$","default":"#111827"},"balance":{"type":"number","minimum":0,"default":0},"clabe":{"type":"string","maxLength":40,"nullable":true},"provider":{"type":"string","maxLength":70,"nullable":true},"isDefault":{"type":"boolean","default":false}},"required":["name"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/categories":{"get":{"summary":"List categories in the active workspace","tags":["categories"],"operationId":"listCategories","security":[{"apiKey":[]},{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}},"post":{"summary":"Create a category","tags":["categories"],"operationId":"postCategories","security":[{"apiKey":[]},{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"icon":{"type":"string","minLength":1,"maxLength":50,"default":"tag"},"description":{"type":"string","maxLength":255,"nullable":true},"color":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$","default":"#6366f1"},"isDefault":{"type":"boolean","default":false},"tagId":{"type":"string","format":"uuid","nullable":true}},"required":["name"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/transactions":{"get":{"summary":"List transactions with filters and pagination","tags":["transactions"],"operationId":"listTransactions","security":[{"apiKey":[]},{"bearerAuth":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1}},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["income","expense","transfer","goal_deposit","goal_withdrawal"]}},{"name":"walletId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"categoryId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"goalId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"from","in":"query","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","required":false,"schema":{"type":"string"}},{"name":"search","in":"query","required":false,"schema":{"type":"string","maxLength":200}}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}},"post":{"summary":"Create a transaction (income / expense / transfer / goal movement)","description":"Wallet balances and goal `savedAmount` are updated atomically. Pass `Idempotency-Key` to safely retry without duplicating.","tags":["transactions"],"operationId":"postTransactions","security":[{"apiKey":[]},{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["income","expense","transfer","goal_deposit","goal_withdrawal"]},"amount":{"type":"number","minimum":0},"date":{"type":"string"},"concept":{"type":"string","maxLength":255,"nullable":true},"description":{"type":"string","maxLength":2000,"nullable":true},"categoryId":{"type":"string","format":"uuid","nullable":true},"walletId":{"type":"string","format":"uuid","nullable":true},"toWalletId":{"type":"string","format":"uuid","nullable":true},"goalId":{"type":"string","format":"uuid","nullable":true},"debtId":{"type":"string","format":"uuid","nullable":true},"tagId":{"type":"string","format":"uuid","nullable":true},"referenceNumber":{"type":"string","maxLength":100,"nullable":true},"attachmentUrl":{"type":"string","format":"uri","nullable":true}},"required":["type","amount","date"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/budgets":{"get":{"summary":"List budgets with current-period spent","tags":["budgets"],"operationId":"listBudgets","security":[{"apiKey":[]},{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}},"post":{"summary":"Create a budget","tags":["budgets"],"operationId":"postBudgets","security":[{"apiKey":[]},{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"categoryId":{"type":"string","format":"uuid"},"amount":{"type":"number","minimum":0},"period":{"type":"string","enum":["weekly","biweekly","semi_monthly","monthly","quarterly","yearly"],"default":"monthly"},"startDate":{"type":"string"},"endDate":{"type":"string"},"alertThreshold":{"type":"number","minimum":1,"maximum":100,"default":80},"tagId":{"type":"string","format":"uuid","nullable":true}},"required":["name","categoryId","amount","startDate","endDate"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/goals/{id}/deposit":{"post":{"summary":"Deposit funds into a goal","tags":["goals"],"operationId":"postGoalsDeposit","security":[{"apiKey":[]},{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"amount":{"type":"number","minimum":0},"walletId":{"type":"string","format":"uuid"},"note":{"type":"string","maxLength":500,"nullable":true},"date":{"type":"string"}},"required":["amount","walletId"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/goals/{id}/withdraw":{"post":{"summary":"Withdraw funds from a goal","description":"If `walletId` is omitted, the amount is distributed proportionally across the wallets that originally funded the goal.","tags":["goals"],"operationId":"postGoalsWithdraw","security":[{"apiKey":[]},{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"amount":{"type":"number","minimum":0},"walletId":{"type":"string","format":"uuid","nullable":true},"note":{"type":"string","maxLength":500,"nullable":true},"date":{"type":"string"}},"required":["amount"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/me":{"get":{"summary":"Usuario actual + workspace activo","tags":["profile"],"operationId":"listMe","security":[{"apiKey":[]},{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}},"patch":{"summary":"Actualizar perfil de usuario","tags":["profile"],"operationId":"patchMe","security":[{"apiKey":[]},{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"firstName":{"type":"string","maxLength":100},"lastName":{"type":"string","maxLength":100},"currency":{"type":"string"},"language":{"type":"string","maxLength":10},"theme":{"type":"string","enum":["light","dark","system"]},"notificationsEnabled":{"type":"boolean"},"hasCompletedOnboarding":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}},"delete":{"summary":"Eliminar el usuario actual (Zona de peligro)","description":"Cancela suscripciones de Stripe, revoca claves de API y elimina lógicamente el usuario y su espacio personal.","tags":["profile"],"operationId":"deleteMe","security":[{"apiKey":[]},{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/api-keys":{"get":{"summary":"List workspace API keys","description":"Returns all API keys for the active workspace, with prefix only (never plaintext). Use POST to create a new one and store the returned `plaintext` in a secret manager.","tags":["api-keys"],"operationId":"listApiKeys","security":[{"apiKey":[]},{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}},"post":{"summary":"Create a workspace API key","description":"Returns the plaintext key in the response **once** — store it immediately. Subsequent reads will only ever expose the `prefix`.","tags":["api-keys"],"operationId":"postApiKeys","security":[{"apiKey":[]},{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"description":{"type":"string","maxLength":2000,"nullable":true},"scopes":{"type":"array","items":{"type":"string"}},"expiresAt":{"type":"string","format":"date-time","nullable":true}},"required":["name","scopes"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/api-keys/{id}":{"delete":{"summary":"Revoke an API key","tags":["api-keys"],"operationId":"deleteApiKeys","security":[{"apiKey":[]},{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/webhooks/outbound":{"get":{"summary":"List outbound webhooks","tags":["webhooks"],"operationId":"listWebhooksOutbound","security":[{"apiKey":[]},{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}},"post":{"summary":"Subscribe a URL to workspace events","description":"The response includes the generated `secret`. Use it to verify HMAC signatures on incoming deliveries (`X-Money-Manager-Signature`).","tags":["webhooks"],"operationId":"postWebhooksOutbound","security":[{"apiKey":[]},{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","minLength":1},"default":["*"]}},"required":["name","url"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/agent/context":{"get":{"summary":"Aggregated workspace context for AI agents","description":"Returns wallets, categories, active goals, active budgets, recent transaction stats and currency settings. Use this once at the start of a conversation; cache results for ~5 minutes.","tags":["agent"],"operationId":"listAgentContext","security":[{"apiKey":[]},{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/audit":{"get":{"summary":"List audit log entries","tags":["audit"],"operationId":"listAudit","security":[{"apiKey":[]},{"bearerAuth":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1}},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"entity","in":"query","required":false,"schema":{"type":"string","maxLength":64}},{"name":"action","in":"query","required":false,"schema":{"type":"string","enum":["create","update","delete"]}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/transactions/bulk":{"post":{"summary":"Bulk delete or recategorize transactions","tags":["transactions"],"operationId":"postTransactionsBulk","security":[{"apiKey":[]},{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string","format":"uuid"}},"operation":{"type":"string","enum":["delete","recategorize"]},"categoryId":{"type":"string","format":"uuid"}},"required":["ids","operation"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/webhooks/incoming":{"post":{"summary":"Incoming webhook ingress for registering transactions","description":"Allows external systems to register transactions (expenses, income) in a workspace. Can be authenticated via header `x-api-key` or query parameter `?key=mm_live_...`","tags":["webhooks"],"operationId":"postWebhooksIncoming","security":[{"apiKey":[]},{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"amount":{"oneOf":[{"type":"number"},{"type":"string"}]},"type":{"type":"string","enum":["income","expense","transfer"],"default":"expense"},"concept":{"type":"string","minLength":1},"description":{"type":"string"},"date":{"type":"string"},"walletId":{"type":"string","format":"uuid"},"walletName":{"type":"string"},"categoryId":{"type":"string","format":"uuid"},"categoryName":{"type":"string"}},"required":["amount","concept"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/reports":{"get":{"summary":"Generate a financial report","description":"JSON, CSV or PDF. Filter by date range, wallet, category.","tags":["reports"],"operationId":"listReports","security":[{"apiKey":[]},{"bearerAuth":[]}],"parameters":[{"name":"from","in":"query","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","required":false,"schema":{"type":"string"}},{"name":"walletId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"categoryId","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv","pdf"],"default":"json"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"example":null}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}}}}