{
  "openapi": "3.1.1",
  "info": {
    "title": "Octbooks.Api | v1",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://www.octbooks.co.uk/"
    }
  ],
  "paths": {
    "/api/reconciliation/consent/start": {
      "post": {
        "tags": [
          "Reconciliation"
        ],
        "summary": "Begins a bank connection and returns the URL to send the user to.",
        "operationId": "StartBankConsent",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/reconciliation/consent/callback": {
      "get": {
        "tags": [
          "Reconciliation"
        ],
        "summary": "Where the aggregator returns the user after they consent.",
        "operationId": "BankConsentCallback",
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "state",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "error",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/ledger/accounts": {
      "get": {
        "tags": [
          "Ledger"
        ],
        "summary": "The chart of accounts for the current tenant.",
        "operationId": "ListAccounts",
        "parameters": [
          {
            "name": "includeInactive",
            "in": "query",
            "required": true,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      },
      "post": {
        "tags": [
          "Ledger"
        ],
        "operationId": "CreateAccount",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAccountRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/ledger/journal-entries": {
      "post": {
        "tags": [
          "Ledger"
        ],
        "summary": "Posts a balanced double-entry journal.",
        "operationId": "PostJournalEntry",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostJournalEntryRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/ledger/trial-balance": {
      "get": {
        "tags": [
          "Ledger"
        ],
        "operationId": "GetTrialBalance",
        "parameters": [
          {
            "name": "asOf",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/invoices": {
      "get": {
        "tags": [
          "Invoicing"
        ],
        "operationId": "ListInvoices",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/InvoiceStatus"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      },
      "post": {
        "tags": [
          "Invoicing"
        ],
        "operationId": "CreateInvoice",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateInvoiceRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/invoices/{id}": {
      "get": {
        "tags": [
          "Invoicing"
        ],
        "operationId": "GetInvoice",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/invoices/{id}/issue": {
      "post": {
        "tags": [
          "Invoicing"
        ],
        "summary": "Issues a draft invoice and publishes it to the ledger.",
        "operationId": "IssueInvoice",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/reconciliation/connections": {
      "get": {
        "tags": [
          "Reconciliation"
        ],
        "operationId": "ListBankConnections",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/reconciliation/connections/{id}/sync": {
      "post": {
        "tags": [
          "Reconciliation"
        ],
        "summary": "Queues a bank feed pull for the given window.",
        "operationId": "RequestBankSync",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SyncRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/reconciliation/transactions/unmatched": {
      "get": {
        "tags": [
          "Reconciliation"
        ],
        "operationId": "ListUnmatchedTransactions",
        "parameters": [
          {
            "name": "connectionId",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/reconciliation/transactions/{id}/match": {
      "post": {
        "tags": [
          "Reconciliation"
        ],
        "operationId": "MatchTransaction",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MatchRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/reconciliation/transactions/{id}/ignore": {
      "post": {
        "tags": [
          "Reconciliation"
        ],
        "operationId": "IgnoreTransaction",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/tax/vat/obligations": {
      "get": {
        "tags": [
          "Tax / MTD"
        ],
        "operationId": "ListVatObligations",
        "parameters": [
          {
            "name": "openOnly",
            "in": "query",
            "required": true,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/tax/vat/returns/{periodKey}/build": {
      "post": {
        "tags": [
          "Tax / MTD"
        ],
        "summary": "Recalculates the nine boxes for a period from the ledger.",
        "operationId": "BuildVatReturn",
        "parameters": [
          {
            "name": "periodKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/tax/vat/returns/{periodKey}": {
      "get": {
        "tags": [
          "Tax / MTD"
        ],
        "operationId": "GetVatReturn",
        "parameters": [
          {
            "name": "periodKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/tax/vat/returns/{periodKey}/submit": {
      "post": {
        "tags": [
          "Tax / MTD"
        ],
        "summary": "Finalises a return and queues it for filing with HMRC.",
        "operationId": "SubmitVatReturn",
        "parameters": [
          {
            "name": "periodKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmitVatReturnRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/reports/trial-balance": {
      "get": {
        "tags": [
          "Reporting"
        ],
        "operationId": "TrialBalanceReport",
        "parameters": [
          {
            "name": "asOf",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/reports/profit-and-loss": {
      "get": {
        "tags": [
          "Reporting"
        ],
        "operationId": "ProfitAndLossReport",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/reports/balance-sheet": {
      "get": {
        "tags": [
          "Reporting"
        ],
        "operationId": "BalanceSheetReport",
        "parameters": [
          {
            "name": "asOf",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/billing/subscription": {
      "get": {
        "tags": [
          "Billing"
        ],
        "operationId": "GetSubscription",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/billing/entitlements": {
      "get": {
        "tags": [
          "Billing"
        ],
        "operationId": "ListEntitlements",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AccountType": {
        "enum": [
          "Asset",
          "Liability",
          "Equity",
          "Income",
          "Expense"
        ]
      },
      "CreateAccountRequest": {
        "required": [
          "code",
          "name",
          "type",
          "currencyCode"
        ],
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "$ref": "#/components/schemas/AccountType"
          },
          "currencyCode": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "CreateInvoiceLineRequest": {
        "required": [
          "description",
          "quantity",
          "unitPrice",
          "vatTreatment"
        ],
        "type": "object",
        "properties": {
          "description": {
            "type": "string"
          },
          "quantity": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "unitPrice": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "vatTreatment": {
            "$ref": "#/components/schemas/VatTreatment"
          }
        }
      },
      "CreateInvoiceRequest": {
        "required": [
          "customerName",
          "issuedOn",
          "dueOn",
          "lines",
          "customerEmail",
          "currencyCode"
        ],
        "type": "object",
        "properties": {
          "customerName": {
            "type": "string"
          },
          "issuedOn": {
            "type": "string",
            "format": "date"
          },
          "dueOn": {
            "type": "string",
            "format": "date"
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreateInvoiceLineRequest"
            }
          },
          "customerEmail": {
            "type": [
              "null",
              "string"
            ]
          },
          "currencyCode": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "InvoiceStatus": {
        "enum": [
          "Draft",
          "Issued",
          "PartPaid",
          "Paid",
          "Void",
          null
        ]
      },
      "JournalLineRequest": {
        "required": [
          "accountId",
          "debit",
          "credit",
          "description"
        ],
        "type": "object",
        "properties": {
          "accountId": {
            "type": "string",
            "format": "uuid"
          },
          "debit": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "credit": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "MatchRequest": {
        "required": [
          "nominalAccountId"
        ],
        "type": "object",
        "properties": {
          "nominalAccountId": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "PostJournalEntryRequest": {
        "required": [
          "postedOn",
          "narrative",
          "lines",
          "currencyCode"
        ],
        "type": "object",
        "properties": {
          "postedOn": {
            "type": "string",
            "format": "date"
          },
          "narrative": {
            "type": "string"
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JournalLineRequest"
            }
          },
          "currencyCode": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "SubmitVatReturnRequest": {
        "required": [
          "vatRegistrationNumber",
          "declarationAccepted"
        ],
        "type": "object",
        "properties": {
          "vatRegistrationNumber": {
            "type": "string"
          },
          "declarationAccepted": {
            "type": "boolean"
          }
        }
      },
      "SyncRequest": {
        "required": [
          "from",
          "to"
        ],
        "type": "object",
        "properties": {
          "from": {
            "type": "string",
            "format": "date"
          },
          "to": {
            "type": "string",
            "format": "date"
          }
        }
      },
      "VatTreatment": {
        "enum": [
          "Standard",
          "Reduced",
          "Zero",
          "Exempt",
          "OutsideScope",
          "ReverseCharge"
        ]
      }
    }
  },
  "tags": [
    {
      "name": "Reconciliation"
    },
    {
      "name": "Ledger"
    },
    {
      "name": "Invoicing"
    },
    {
      "name": "Tax / MTD"
    },
    {
      "name": "Reporting"
    },
    {
      "name": "Billing"
    }
  ]
}