{"openapi":"3.1.0","info":{"title":"POST /api/v1/ledgers/merge","version":"1.0.0","description":"Merge ledgers"},"servers":[{"url":"https://api.ondayzero.com","description":"Production"}],"paths":{"/api/v1/ledgers/merge":{"post":{"tags":["ledgers"],"summary":"Merge ledgers","description":"Merge one or more source ledgers into a target ledger, reassigning all transactions and journal entries.","operationId":"merge_ledgers","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-business-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Business-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LedgerMergeRequest"},"example":{"new_name":"Software & Subscriptions","source_ledger_ids":["0192a4f0-1b2c-7d3e-8f4a-5b6c7d8e9f12"],"target_ledger_id":"0192a4f0-1b2c-7d3e-8f4a-5b6c7d8e9f11"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope_LedgerMergeResponse_"}}}},"400":{"description":"Bad Request - Invalid input","content":{"application/json":{"example":{"error":"validation_error","message":"Validation failed: due_date: Input should be a valid date","errors":{"due_date":"Input should be a valid date"},"code":"GEN_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized - Missing or expired token, an MCP OAuth token used against the REST API, or no access to this business","content":{"application/json":{"example":{"error":"unauthorized","message":"Authentication required","code":"AUTH_001","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"example":{"error":"forbidden","message":"You don't have permission to access this resource","code":"AUTH_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found - Resource does not exist","content":{"application/json":{"example":{"error":"not_found","message":"Resource not found","code":"NOT_FOUND_001","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict - Resource already exists or is in an incompatible state","content":{"application/json":{"example":{"error":"conflict","message":"Resource already exists","code":"CONFLICT_001","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"validation_error","message":"Validation failed: amount: Input should be a valid integer","errors":{"amount":"Input should be a valid integer"},"code":"GEN_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"}}}}},"x-fastapi-operation-id":"merge_ledgers_api_v1_ledgers_merge_post"}}},"components":{"schemas":{"CashFlowClassEnum":{"type":"string","enum":["cash","ar","inventory","prepaid","other_current_asset","ppe","intangible","other_lt_asset","investments","intercompany_asset","internal_transfer","ap","cc_payable","accrued","other_current_liability","lt_debt","intercompany_liability","equity_contribution","equity_distribution","retained_earnings","revenue","cogs","opex","non_cash_expense","interest_expense","tax_expense"],"title":"CashFlowClassEnum","description":"Indirect-method cash flow classification for ledgers.\n\nEach chart-of-account row carries one of these in addition to its\nbroader ``type``. The indirect cash flow statement is built by\ngrouping period-over-period balance deltas by this column.\nMirrors ``app.models.ledgers.CashFlowClassEnum`` for API surface."},"CashFlowSectionEnum":{"type":"string","enum":["operating","investing","financing","excluded"],"title":"CashFlowSectionEnum","description":"Cash flow statement section classification for ledgers."},"DepreciationTagEnum":{"type":"string","enum":["depreciable","amortizable"],"title":"DepreciationTagEnum","description":"Marks a ledger as holding capitalizable spend.\n\nMirrors ``app.models.ledgers.DepreciationTagEnum`` for API surface.\nTagged ledgers are offered as sources when creating fixed assets from\nthe transactions assigned to them."},"LedgerMergeRequest":{"properties":{"source_ledger_ids":{"items":{"type":"string"},"type":"array","minItems":1,"title":"Source Ledger Ids","description":"One or more ledger UUIDs to merge FROM (will be archived after merge)."},"target_ledger_id":{"type":"string","title":"Target Ledger Id","description":"The ledger UUID to merge INTO (receives all reassigned data)."},"new_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"New Name","description":"Optional new name for the target ledger after merge."},"confirmation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Confirmation","description":"Required when merging system ledgers into another system ledger: must be the literal string 'MERGE'."}},"type":"object","required":["source_ledger_ids","target_ledger_id"],"title":"LedgerMergeRequest","description":"Request schema for merging one or more source ledgers into a target ledger.\n\nAll line entries, transactions, budgets, reconciliations, and other\nreferences pointing at the source ledgers are reassigned to the target.\nSource ledgers are then archived (set to inactive).","example":{"new_name":"Software & Subscriptions","source_ledger_ids":["0192a4f0-1b2c-7d3e-8f4a-5b6c7d8e9f12"],"target_ledger_id":"0192a4f0-1b2c-7d3e-8f4a-5b6c7d8e9f11"},"examples":[{"new_name":"Software & Subscriptions","source_ledger_ids":["0192a4f0-1b2c-7d3e-8f4a-5b6c7d8e9f12"],"target_ledger_id":"0192a4f0-1b2c-7d3e-8f4a-5b6c7d8e9f11"}]},"LedgerMergeResponse":{"properties":{"task_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task Id","description":"Temporal workflow / task ID for async Teal merges. Poll GET /tasks/{task_id} for status."},"message":{"type":"string","title":"Message","description":"Human-readable status message."},"merged_ledger":{"anyOf":[{"$ref":"#/components/schemas/LedgerResponse"},{"type":"null"}],"description":"The updated target ledger (present for synchronous local-engine merges)."}},"type":"object","required":["message"],"title":"LedgerMergeResponse","description":"Response schema for a ledger merge operation.\n\nFor local-engine businesses the merge completes synchronously and\n``items`` contains the updated target ledger.\n\nFor Teal-engine businesses the merge runs asynchronously via a\nTemporal workflow; ``task_id`` can be polled for progress."},"LedgerResponse":{"properties":{"id":{"type":"string","title":"Id","description":"Ledger UUID."},"teal_ledger_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Teal Ledger Id","description":"Linked Teal accounting system ID."},"name":{"type":"string","title":"Name","description":"Account name."},"currency":{"type":"string","title":"Currency","description":"Currency for this account (USD, CAD, AUD, EUR, or GBP).","default":"USD"},"type":{"type":"string","title":"Type","description":"Account type: asset, liability, equity, revenue, expense."},"balance":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Balance","description":"Current balance in cents (may be negative)."},"parent_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parent Id","description":"Parent ledger UUID for sub-accounts."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Account description."},"account_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Number","description":"Optional account number/code for chart-of-accounts numbering."},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status","description":"Status: 'active' or 'inactive'."},"debit_credit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Debit Credit","description":"Normal balance: 'debit' or 'credit'."},"sort_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sort Code","description":"Sort code for chart ordering."},"sub_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sub Type","description":"Sub-classification for reporting."},"report_cash_flow":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Report Cash Flow","description":"Whether included in cash flow statement."},"cash_flow_section":{"anyOf":[{"$ref":"#/components/schemas/CashFlowSectionEnum"},{"type":"null"}],"description":"Cash flow statement section: 'operating', 'investing', 'financing', or 'excluded'."},"cfs_class":{"anyOf":[{"$ref":"#/components/schemas/CashFlowClassEnum"},{"type":"null"}],"description":"Indirect-method cash flow classification used to populate the Statement of Cash Flows."},"depreciation_tag":{"anyOf":[{"$ref":"#/components/schemas/DepreciationTagEnum"},{"type":"null"}],"description":"Marks this account as holding capitalizable spend: 'depreciable' or 'amortizable'. Null when untagged."},"editable":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Editable","description":"Whether journal entries can be manually posted to this account."},"financial_account_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Financial Account Type","description":"Template type if created in Templated Mode."},"is_required":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Required","description":"True for system-required accounts that cannot be deleted."},"system_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"System Key","description":"Immutable key for system/base ledgers (e.g. 'accounts_receivable'). Null for user-created ledgers."},"teal_account_link_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Teal Account Link Id","description":"UUID of the TealAccountLink if this ledger is connected to a bank/Plaid source account. Null for unlinked ledgers."},"account_mask":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Mask","description":"Last 4 digits of the connected bank/card account, as reported by the provider. Identifies the card behind a ledger whose name does not carry it (Plaid names every Brex card \"Brex Card Account\"). Null for unlinked ledgers or when the provider returned no mask. Display convention is ``****1234``."},"business_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Id","description":"Business UUID."},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At","description":"Creation timestamp."},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At","description":"Last update timestamp."}},"additionalProperties":true,"type":"object","required":["id","name","type"],"title":"LedgerResponse","description":"Response schema for a ledger (chart of accounts entry).\n\nA ledger represents an account in the chart of accounts. Each ledger\nhas a type (asset, liability, etc.), current balance, and configuration\nfor how it affects financial reports.","example":{"account_number":"1010","balance":1523450,"business_id":"019ab37c-b051-7000-8000-000000000001","created_at":"2024-01-10T10:30:00Z","debit_credit":"debit","description":"Primary operating account","editable":true,"financial_account_type":"bank_account","id":"019ab37c-1ed1-7000-8000-000000000001","is_required":false,"name":"Chase Business Checking","report_cash_flow":true,"sort_code":"1010","status":"active","sub_type":"current_assets","teal_ledger_id":"led_abc123","type":"asset","updated_at":"2024-01-15T14:00:00Z"},"examples":[{"account_number":"1010","balance":1523450,"business_id":"019ab37c-b051-7000-8000-000000000001","created_at":"2024-01-10T10:30:00Z","debit_credit":"debit","description":"Primary operating account","editable":true,"financial_account_type":"bank_account","id":"019ab37c-1ed1-7000-8000-000000000001","is_required":false,"name":"Chase Business Checking","report_cash_flow":true,"sort_code":"1010","status":"active","sub_type":"current_assets","teal_ledger_id":"led_abc123","type":"asset","updated_at":"2024-01-15T14:00:00Z"}]},"SuccessEnvelope_LedgerMergeResponse_":{"properties":{"success":{"type":"boolean","title":"Success","default":true},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"data":{"anyOf":[{"$ref":"#/components/schemas/LedgerMergeResponse"},{"type":"null"}]}},"additionalProperties":true,"type":"object","title":"SuccessEnvelope[LedgerMergeResponse]"},"ErrorResponse":{"title":"ErrorResponse","type":"object","description":"Envelope returned by every non-2xx response. Branch on `code` (stable) rather than `message` (human-readable, may change).","required":["error","message","code"],"properties":{"error":{"type":"string","description":"Error category: `validation_error`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `rate_limited`, `server_error`, or `service_unavailable`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to end users."},"code":{"type":"string","description":"Stable machine-readable code in `CATEGORY_NNN` form (e.g. `NOT_FOUND_006`, `AUTH_010`, `GEN_002`)."},"request_id":{"type":"string","description":"Correlation id for support requests. Echoes the `x-request-id` request header when one was supplied."},"errors":{"type":"object","additionalProperties":{"type":"string"},"description":"Field-level validation messages keyed by field name. Present on 400/422 validation failures only."}}}},"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Token","description":"API token authentication. Format: `Bearer dz_...`"}}},"security":[{"BearerAuth":[]}]}