{"openapi":"3.1.0","info":{"title":"Set Aside Money API","version":"1.0.0","description":"Read and update a Set Aside Money account programmatically.\n\nAuthenticate with a personal API key created in the app under Settings, Developer API.\nSend it as `Authorization: Bearer sam_live_...`. Keys carry either the `data.read` scope or\nboth `data.read` and `data.write`.\n\nAll monetary amounts are integer cents."},"servers":[{"url":"https://api.setaside.money/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"A personal API key beginning with `sam_live_`."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","enum":["invalid_request","authentication_error","permission_error","not_found","conflict","rate_limit_error","api_error"]},"code":{"type":"string","description":"A stable, machine-readable identifier for this failure."},"message":{"type":"string"},"param":{"type":"string","description":"The offending parameter, when the failure is about one."},"request_id":{"type":"string","description":"Quote this when contacting support."}},"required":["type","code","message"]}},"required":["error"]}}},"paths":{"/simplefin/items/{id}/accounts":{"get":{"operationId":"getSimplefinAccountSelection","summary":"Read SimpleFIN account subscriptions","description":"Reads the saved selection without contacting SimpleFIN.","security":[{"apiKey":["data.read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"accounts":{"type":"array","items":{"type":"object","properties":{},"additionalProperties":{}}}},"required":["accounts"],"additionalProperties":{}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"setSimplefinAccountSelection","summary":"Subscribe or unsubscribe SimpleFIN accounts","description":"Connection owner only. Replaces the selection using catalog IDs, retains history and cursors, and schedules imports. Empty selection pauses all requests. Resubscription retrieves only history still available from the provider.","security":[{"apiKey":["data.write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"account_ids":{"maxItems":500,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}},"required":["account_ids"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"accounts":{"type":"array","items":{"type":"object","properties":{},"additionalProperties":{}}}},"required":["accounts"],"additionalProperties":{}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/simplefin/items/{id}/discover":{"post":{"operationId":"discoverSimplefinAccounts","summary":"Discover SimpleFIN accounts for selection","description":"Connection owner only. Explicit balances-only discovery consumes Bridge request quota. Never subscribes accounts or imports transactions.","security":[{"apiKey":["data.write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"accounts":{"type":"array","items":{"type":"object","properties":{},"additionalProperties":{}}}},"required":["accounts"],"additionalProperties":{}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/accounts/{id}/subscription":{"put":{"operationId":"setAccountSubscription","summary":"Subscribe or unsubscribe a bank account","description":"Connection owner only. Stops new imports and notifications while retaining stored history and Expense links. SimpleFIN keeps last imported balances visible. Plaid also hides the account and its transactions; the bank connection stays active and counts toward its limit. Resubscription retrieves only provider-available history.","security":[{"apiKey":["data.write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"subscribed":{"type":"boolean"}},"required":["subscribed"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"subscribed":{"type":"boolean"},"history_retained":{"type":"boolean"}},"required":["subscribed","history_retained"],"additionalProperties":false}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/me":{"get":{"operationId":"getCurrentKey","summary":"Describe the calling key","description":"Returns the account the key belongs to, its scopes, and its current rate-limit state. Useful as a connectivity check.","security":[{"apiKey":["data.read"]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"account_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"scopes":{"type":"array","items":{"type":"string"}},"key":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"expires_at":{"type":"string"}},"required":["id","expires_at"],"additionalProperties":false},"rate_limit":{"type":"object","properties":{"minute_limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"minute_remaining":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"hour_limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"hour_remaining":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["minute_limit","minute_remaining","hour_limit","hour_remaining"],"additionalProperties":false}},"required":["account_id","scopes","key","rate_limit"],"additionalProperties":false}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/accounts":{"get":{"operationId":"listAccounts","summary":"List accounts","description":"Every visible account connected to this Set Aside Money account.","security":[{"apiKey":["data.read"]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"type":{"type":"string"},"subtype":{"anyOf":[{"type":"string"},{"type":"null"}]},"currency":{"type":"string"},"balance":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Balance in cents."}},"required":["id","name","type","subtype","currency","balance"],"additionalProperties":{}}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/accounts/summary":{"get":{"operationId":"getAccountsSummary","summary":"Get account totals","description":"Balance rollups across all accounts.","security":[{"apiKey":["data.read"]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/connections":{"get":{"operationId":"listConnections","summary":"List bank connections","description":"Provider connections and their sync state.","security":[{"apiKey":["data.read"]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{},"additionalProperties":{}}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/transactions":{"get":{"operationId":"listTransactions","summary":"List transactions","description":"Search and filter transactions. Paginated.","security":[{"apiKey":["data.read"]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200}},{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["expense","income","transfer"]}},{"name":"account_id","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"category_id","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"expense_goal_id","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"search","in":"query","required":false,"schema":{"type":"string","maxLength":120}},{"name":"from","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["booked_at","created_at"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"account_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"concept":{"type":"string"},"original_concept":{"description":"Raw provider descriptor, when it differs from the parsed concept. Null if the concept is already what the provider sent.","anyOf":[{"type":"string"},{"type":"null"}]},"amount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount in cents."},"booked_at":{"type":"string"},"type":{"type":"string"},"category_id":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"expense_goal_id":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["id","account_id","concept","amount","booked_at","type","category_id","expense_goal_id"],"additionalProperties":{}}},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"page":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"pages":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["data","total","page","pages"],"additionalProperties":{}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createTransaction","summary":"Create a transaction","description":"Records a manual transaction. Supports Idempotency-Key.","security":[{"apiKey":["data.write"]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","minLength":8,"maxLength":128},"description":"Repeat the same key to retry safely without duplicating the effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"account_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount in cents. Negative for spending."},"concept":{"type":"string","minLength":1,"maxLength":200},"booked_at":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"type":{"type":"string","enum":["expense","income","transfer"]},"category_id":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"expense_goal_id":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]}},"required":["account_id","amount","concept","booked_at"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"account_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"concept":{"type":"string"},"original_concept":{"description":"Raw provider descriptor, when it differs from the parsed concept. Null if the concept is already what the provider sent.","anyOf":[{"type":"string"},{"type":"null"}]},"amount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount in cents."},"booked_at":{"type":"string"},"type":{"type":"string"},"category_id":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"expense_goal_id":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["id","account_id","concept","amount","booked_at","type","category_id","expense_goal_id"],"additionalProperties":{}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/transactions/summary":{"get":{"operationId":"getTransactionsSummary","summary":"Summarize transactions","description":"Totals for the selected filters.","security":[{"apiKey":["data.read"]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200}},{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["expense","income","transfer"]}},{"name":"account_id","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"category_id","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"expense_goal_id","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"search","in":"query","required":false,"schema":{"type":"string","maxLength":120}},{"name":"from","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["booked_at","created_at"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/transactions/{id}":{"get":{"operationId":"getTransaction","summary":"Get a transaction","security":[{"apiKey":["data.read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"account_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"concept":{"type":"string"},"original_concept":{"description":"Raw provider descriptor, when it differs from the parsed concept. Null if the concept is already what the provider sent.","anyOf":[{"type":"string"},{"type":"null"}]},"amount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount in cents."},"booked_at":{"type":"string"},"type":{"type":"string"},"category_id":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"expense_goal_id":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["id","account_id","concept","amount","booked_at","type","category_id","expense_goal_id"],"additionalProperties":{}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateTransaction","summary":"Update a transaction","security":[{"apiKey":["data.write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"amount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"concept":{"type":"string","minLength":1,"maxLength":200},"booked_at":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"type":{"type":"string","enum":["expense","income","transfer"]},"category_id":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"],"additionalProperties":{}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/transactions/{id}/expense":{"post":{"operationId":"assignTransactionToExpense","summary":"Assign a transaction to an Expense","description":"Spends the transaction from an Expense or Goal balance. Pass null to clear the assignment.","security":[{"apiKey":["data.write"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"expense_goal_id":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"Expense to assign this transaction to. Null clears the assignment."}},"required":["expense_goal_id"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"],"additionalProperties":{}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/expenses":{"get":{"operationId":"listExpenses","summary":"List Expenses","description":"Expenses, Goals, and credit card Expenses.","security":[{"apiKey":["data.read"]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"type":{"type":"string","enum":["expense","goal","credit_card"]},"target_amount":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"balance":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount currently set aside, in cents."},"funding_priority":{"type":"string","enum":["high","normal","low"]},"recurrence_interval_months":{"anyOf":[{"type":"number","const":1},{"type":"number","const":3},{"type":"number","const":6},{"type":"number","const":12}]},"recurrence_anchor_date":{"anyOf":[{"type":"string"},{"type":"null"}]},"fund_ahead_payment_count":{"type":"integer","minimum":1,"maximum":3},"fund_ahead_build_by":{"anyOf":[{"type":"string"},{"type":"null"}]},"ordinaryBalance":{"description":"Ordinary portion of total balance, in cents.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"extraReserve":{"description":"Extra reserve already included in balance, in cents; never add it again.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"reserveGoal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"reserveShortfall":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"ordinaryContribution":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"fundAheadContribution":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"paymentsReserved":{"description":"Actual total balance divided by the payment target.","type":"number"}},"required":["id","name","type","target_amount","balance"],"additionalProperties":{}}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/expenses/summary":{"get":{"operationId":"getExpensesSummary","summary":"Get Expense totals","security":[{"apiKey":["data.read"]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/expense-groups":{"get":{"operationId":"listExpenseGroups","summary":"List Expense groups","security":[{"apiKey":["data.read"]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{},"additionalProperties":{}}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/expense-transfers":{"get":{"operationId":"listExpenseTransfers","summary":"List transfers between Expenses","security":[{"apiKey":["data.read"]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{},"additionalProperties":{}}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createExpenseTransfer","summary":"Move money between Expenses","description":"Moves an amount from one Expense to another. Supports Idempotency-Key, which is honored end to end by the ledger.","security":[{"apiKey":["data.write"]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","minLength":8,"maxLength":128},"description":"Repeat the same key to retry safely without duplicating the effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"from_expense_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"to_expense_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amount":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"Amount in cents."},"note":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]}},"required":["from_expense_id","to_expense_id","amount"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/categories":{"get":{"operationId":"listCategories","summary":"List categories","security":[{"apiKey":["data.read"]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{},"additionalProperties":{}}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/funding-schedules":{"get":{"operationId":"listFundingSchedules","summary":"List funding schedules","security":[{"apiKey":["data.read"]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{},"additionalProperties":{}}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/settings":{"get":{"operationId":"getSettings","summary":"Get account settings","security":[{"apiKey":["data.read"]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/analytics/net-worth":{"get":{"operationId":"getNetWorth","summary":"Get net worth","security":[{"apiKey":["data.read"]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/analytics/spending":{"get":{"operationId":"getSpending","summary":"Get spending analytics","security":[{"apiKey":["data.read"]}],"parameters":[{"name":"from","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"group_by","in":"query","required":false,"schema":{"type":"string","enum":["category","merchant","month"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sync/status":{"get":{"operationId":"getSyncStatus","summary":"Get sync status","security":[{"apiKey":["data.read"]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sync":{"post":{"operationId":"startSync","summary":"Trigger a sync","description":"Asks connected providers for new transactions. Providers enforce their own refresh quotas, so this can return 429 with a provider_quota_exhausted code.","security":[{"apiKey":["data.write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"provider":{"type":"string","enum":["plaid","simplefin"]}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":{}}}}},"400":{"description":"The request was not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The API key is missing, malformed, revoked, or no longer entitled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or the plan does not include this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was exceeded. See Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}