openapi: 3.0.3
info:
  title: 'E-Filing API V3'
  version: 3.0.0
  license:
    name: Proprietary
  description: "## Data Conventions\n- **IDs**: Strings to preserve leading zeros - if applicable (e.g., \"00000001\")\n- **Dates**: 14-character strings in YmdHis format (e.g., \"20020223000000\")\n- **Money**: Typically, Strings formatted to 2 decimal places (e.g., \"123.45\")\n- **Share prices**: Strings with up to 6 decimal places (e.g., \"1.50\", \"0.000001\")\n- **Status codes**: Integers (filterable by single value or comma-separated list)\n- **Empty values**: Empty strings (\"\")\n\n## Resources\n- **Users**: User accounts with contacts and addresses\n- **Orders**: Purchase orders with line items and tracking\n- **Incorporations**: Company records with registered office\n- **Officers**: Company officers with addresses and shareholdings\n- **Services**: Service subscriptions\n- **Service Items**: Individual actions/charges related to services\n- **Product Operations**: Product/Service add-ons and operations\n\n## Recommendations\n- **Cursor pagination**: significantly improves performance over page-based pagination for large datasets\n"
  contact:
    name: 'E-Filing API Support'
servers:
  -
    url: 'https://api.efiling.co.uk/3'
    description: Server
tags:
  -
    name: Users
    description: 'User resource operations'
  -
    name: Orders
    description: 'Order resource operations'
  -
    name: 'Order Lines'
    description: 'Order line item operations'
  -
    name: Incorporations
    description: 'Company/Incorporation resource operations'
  -
    name: Services
    description: 'Service subscription operations'
  -
    name: 'Service Items'
    description: 'Service item/task operations'
  -
    name: Products
    description: 'Product resource operations'
paths:
  /users:
    get:
      tags:
        - Users
      summary: 'List all users'
      description: 'Retrieve a paginated list of all users'
      operationId: listUsers
      parameters:
        -
          name: 'filters[statuses]'
          in: query
          required: false
          schema:
            type: string
            pattern: '^[0-9,]+$'
          description: 'Filter by status codes (comma-separated)'
        -
          name: 'filters[createdFrom]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by creation date from (Ymd or YmdHis format)'
        -
          name: 'filters[createdTo]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by creation date to (Ymd or YmdHis format)'
        -
          name: 'filters[updatedFrom]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by update date from (Ymd or YmdHis format)'
        -
          name: 'filters[updatedTo]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by update date to (Ymd or YmdHis format)'
        -
          name: 'page[number]'
          in: query
          schema:
            type: integer
            default: 1
          description: 'Pagination Page number'
        -
          name: 'page[cursor]'
          in: query
          schema:
            type: string
          description: 'Pagination cursor'
      responses:
        200:
          description: 'Successful response'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/UserList'
                  pagination:
                    oneOf:
                      -
                        $ref: '#/components/schemas/Pagination'
                      -
                        $ref: '#/components/schemas/PaginationCursor'
                  errors:
                    type: array
                    items:
                      type: string
                required:
                  - data
                  - pagination
                  - errors
        401:
          description: Unauthorized
    post:
      tags:
        - Users
      summary: 'Create a new user'
      description: 'Create a new user resource'
      operationId: createUser
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/UserCreateUpdate'
      responses:
        201:
          description: 'User created successfully'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        400:
          description: 'Bad request - validation error'
        422:
          description: 'Unprocessable entity'
  '/users/{id}':
    get:
      tags:
        - Users
      summary: 'Get a user by ID'
      description: 'Retrieve a single user by their ID'
      operationId: getUserById
      parameters:
        -
          name: id
          in: path
          required: true
          schema:
            type: string
          description: 'User ID'
      responses:
        200:
          description: 'Successful response'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        404:
          description: 'User not found'
    post:
      tags:
        - Users
      summary: 'Update a user'
      description: 'Update an existing user'
      operationId: updateUser
      parameters:
        -
          name: id
          in: path
          required: true
          schema:
            type: string
          description: 'User ID'
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/UserCreateUpdate'
      responses:
        200:
          description: 'User updated successfully'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        404:
          description: 'User not found'
        400:
          description: 'Bad request - validation error'
  /orders:
    get:
      tags:
        - Orders
      summary: 'List all orders'
      description: 'Retrieve a list of all orders'
      operationId: listOrders
      parameters:
        -
          name: 'filters[statuses]'
          in: query
          schema:
            type: string
            pattern: '^[0-9,]+$'
          description: 'Filter by order status codes (comma-separated)'
        -
          name: 'filters[createdFrom]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by creation date from (Ymd or YmdHis format)'
        -
          name: 'filters[createdTo]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by creation date to (Ymd or YmdHis format)'
        -
          name: 'filters[updatedFrom]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by update date from (Ymd or YmdHis format)'
        -
          name: 'filters[updatedTo]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by update date to (Ymd or YmdHis format)'
        -
          name: 'filters[invoicedFrom]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by invoiced date from (Ymd or YmdHis format)'
        -
          name: 'filters[invoicedTo]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by invoiced date to (Ymd or YmdHis format)'
        -
          name: 'page[number]'
          in: query
          schema:
            type: integer
          description: 'Page number'
        -
          name: 'page[cursor]'
          in: query
          schema:
            type: string
          description: 'Pagination cursor'
      responses:
        200:
          description: 'Successful response'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Order'
                  pagination:
                    oneOf:
                      -
                        $ref: '#/components/schemas/Pagination'
                      -
                        $ref: '#/components/schemas/PaginationCursor'
                  errors:
                    type: array
                    items:
                      type: string
                required:
                  - data
                  - pagination
                  - errors
        401:
          description: Unauthorized
  '/orders/{id}/orderlines':
    get:
      tags:
        - 'Order Lines'
      summary: 'Get order lines for an order'
      description: 'Retrieve all line items for a specific order'
      operationId: getOrderLines
      parameters:
        -
          name: id
          in: path
          required: true
          schema:
            type: string
          description: 'Order ID'
      responses:
        200:
          description: 'Successful response'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/OrderLine'
                  errors:
                    type: array
                    items:
                      type: string
                required:
                  - data
                  - errors
        401:
          description: Unauthorized
  /incorporations:
    get:
      tags:
        - Incorporations
      summary: 'List all incorporations'
      description: 'Retrieve a list of all company/incorporation records'
      operationId: listIncorporations
      parameters:
        -
          name: 'filters[statuses]'
          in: query
          schema:
            type: string
            pattern: '^[0-9,]+$'
          description: 'Filter by company status codes (comma-separated)'
        -
          name: 'filters[createdFrom]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by creation date from (Ymd or YmdHis format)'
        -
          name: 'filters[createdTo]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by creation date to (Ymd or YmdHis format)'
        -
          name: 'filters[updatedFrom]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by update date from (Ymd or YmdHis format)'
        -
          name: 'filters[updatedTo]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by update date to (Ymd or YmdHis format)'
        -
          name: 'filters[incorporatedFrom]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by incorporation date from (Ymd or YmdHis format)'
        -
          name: 'filters[incorporatedTo]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by incorporation date to (Ymd or YmdHis format)'
        -
          name: 'page[number]'
          in: query
          schema:
            type: integer
            default: 1
          description: 'Page number'
        -
          name: 'page[cursor]'
          in: query
          schema:
            type: string
          description: 'Pagination cursor'
      responses:
        200:
          description: 'Successful response'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Incorporation'
                  pagination:
                    oneOf:
                      -
                        $ref: '#/components/schemas/Pagination'
                      -
                        $ref: '#/components/schemas/PaginationCursor'
                  errors:
                    type: array
                    items:
                      type: string
                required:
                  - data
                  - pagination
                  - errors
        401:
          description: Unauthorized
  '/incorporations/{id}':
    get:
      tags:
        - Incorporations
      summary: 'Get an incorporation by ID'
      description: 'Retrieve a single incorporation by its ID'
      operationId: getIncorporationById
      parameters:
        -
          name: id
          in: path
          required: true
          schema:
            type: string
          description: 'Incorporation ID'
      responses:
        200:
          description: 'Successful response'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Incorporation'
        404:
          description: 'Incorporation not found'
  '/incorporations/{id}/officers':
    get:
      tags:
        - Incorporations
      summary: 'Get officers for an incorporation'
      description: 'Retrieve all officers for a specific company'
      operationId: getIncorporationOfficers
      parameters:
        -
          name: id
          in: path
          required: true
          schema:
            type: string
          description: 'Incorporation ID'
      responses:
        200:
          description: 'Successful response'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/IncorporationOfficer'
                  errors:
                    type: array
                    items:
                      type: string
                required:
                  - data
                  - errors
        401:
          description: Unauthorized
  '/incorporations/{id}/dates':
    get:
      tags:
        - Incorporations
      summary: 'Get important dates for an incorporation'
      description: 'Retrieve important dates and deadlines for a specific company'
      operationId: getIncorporationDates
      parameters:
        -
          name: id
          in: path
          required: true
          schema:
            type: string
          description: 'eFiling Incorporation ID'
      responses:
        200:
          description: 'Successful response'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IncorporationDates'
        401:
          description: Unauthorized
  '/incorporations/{id}/services':
    get:
      tags:
        - Incorporations
      summary: 'Get services for an incorporation'
      description: 'Retrieve all service subscriptions for a specific company'
      operationId: getIncorporationServices
      parameters:
        -
          name: id
          in: path
          required: true
          schema:
            type: string
          description: 'Incorporation ID'
      responses:
        200:
          description: 'Successful response'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Service'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
                  errors:
                    type: array
                    items:
                      type: string
                required:
                  - data
                  - pagination
                  - errors
        404:
          description: 'Incorporation not found'
  /services:
    get:
      tags:
        - Services
      summary: 'List all services'
      description: 'Retrieve a list of all service subscriptions'
      operationId: listServices
      parameters:
        -
          name: 'filters[status]'
          in: query
          schema:
            type: integer
          description: 'Filter by service status'
        -
          name: 'filters[createdFrom]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by creation date from (Ymd or YmdHis format)'
        -
          name: 'filters[createdTo]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by creation date to (Ymd or YmdHis format)'
        -
          name: 'filters[renewFrom]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by renewal date from (Ymd or YmdHis format)'
        -
          name: 'filters[renewTo]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by renewal date to (Ymd or YmdHis format)'
        -
          name: 'filters[cancelledFrom]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by cancelled date from (Ymd or YmdHis format)'
        -
          name: 'filters[cancelledTo]'
          in: query
          schema:
            type: string
            pattern: '^[0-9]{8,14}$'
          description: 'Filter by cancelled date to (Ymd or YmdHis format)'
        -
          name: 'filters[limit]'
          in: query
          schema:
            type: integer
            default: 100
            minimum: 1
            maximum: 100
          description: 'Maximum number of results per page'
        -
          name: 'page[number]'
          in: query
          schema:
            type: integer
            default: 1
          description: 'Page number'
      responses:
        200:
          description: 'Successful response'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Service'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
                  errors:
                    type: array
                    items:
                      type: string
                required:
                  - data
                  - pagination
                  - errors
        401:
          description: Unauthorized
  '/services/{id}':
    get:
      tags:
        - Services
      summary: 'Get a service by ID'
      description: 'Retrieve a single service subscription by its ID'
      operationId: getServiceById
      parameters:
        -
          name: id
          in: path
          required: true
          schema:
            type: string
          description: 'Service ID'
      responses:
        200:
          description: 'Successful response'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Service'
        404:
          description: 'Service not found'
  '/services/{id}/items':
    get:
      tags:
        - 'Service Items'
      summary: 'Get service items for a service'
      description: 'Retrieve all items/tasks for a specific service subscription'
      operationId: getServiceItems
      parameters:
        -
          name: id
          in: path
          required: true
          schema:
            type: string
          description: 'Service ID'
        -
          name: 'filters[limit]'
          in: query
          schema:
            type: integer
            default: 100
            minimum: 1
            maximum: 100
          description: 'Maximum number of results per page'
        -
          name: 'page[number]'
          in: query
          schema:
            type: integer
            default: 1
          description: 'Page number'
      responses:
        200:
          description: 'Successful response'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ServiceItem'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
                  errors:
                    type: array
                    items:
                      type: string
                required:
                  - data
                  - pagination
                  - errors
        401:
          description: Unauthorized
    post:
      tags:
        - 'Service Items'
      summary: 'Create a service item'
      description: 'Create a new service item/task for a specific service subscription'
      operationId: createServiceItem
      parameters:
        -
          name: id
          in: path
          required: true
          schema:
            type: string
          description: 'Service ID'
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/ServiceItemCreateUpdate'
      responses:
        201:
          description: 'Service item created successfully'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceItem'
        400:
          description: 'Bad request - validation error'
        404:
          description: 'Service not found'
        422:
          description: 'Unprocessable entity'
  '/services/{id}/items/{serviceItemId}':
    get:
      tags:
        - 'Service Items'
      summary: 'Get a service item by ID'
      description: 'Retrieve a single service item by its ID'
      operationId: getServiceItemById
      parameters:
        -
          name: id
          in: path
          required: true
          schema:
            type: string
          description: 'Service ID'
        -
          name: serviceItemId
          in: path
          required: true
          schema:
            type: string
          description: 'Service item ID'
      responses:
        200:
          description: 'Successful response'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceItem'
        404:
          description: 'Service item not found'
    post:
      tags:
        - 'Service Items'
      summary: 'Update a service item'
      description: 'Update an existing service item for a specific service subscription'
      operationId: updateServiceItem
      parameters:
        -
          name: id
          in: path
          required: true
          schema:
            type: string
          description: 'Service ID'
        -
          name: serviceItemId
          in: path
          required: true
          schema:
            type: string
          description: 'Service item ID'
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/ServiceItemCreateUpdate'
      responses:
        200:
          description: 'Service item updated successfully'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceItem'
        400:
          description: 'Bad request - validation error'
        404:
          description: 'Service item not found'
        422:
          description: 'Unprocessable entity'
  /products:
    get:
      tags:
        - Products
      summary: 'List all products'
      description: 'Retrieve a list of all products'
      operationId: listProducts
      parameters:
        -
          name: 'filters[statuses]'
          in: query
          required: false
          schema:
            type: string
            pattern: '^[0-9,]+$'
          description: 'Filter by status codes (comma-separated)'
        -
          name: 'filters[types]'
          in: query
          required: false
          schema:
            type: string
            pattern: '^[a-zA-Z0-9_,]+$'
          description: 'Filter by product types (comma-separated). Available options include FORM, REGOFFICE, MAILFORWARD, SERVICEADDRESS.'
        -
          name: 'page[number]'
          in: query
          schema:
            type: integer
            default: 1
          description: 'Page number'
      responses:
        200:
          description: 'Successful response'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Product'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
                  errors:
                    type: array
                    items:
                      type: string
                required:
                  - data
                  - pagination
                  - errors
        401:
          description: Unauthorized
  '/products/{id}/operations':
    get:
      tags:
        - Products
      summary: 'Get product operations'
      description: 'Retrieve a list of operations for a specific product.'
      operationId: getProductOperations
      parameters:
        -
          name: id
          in: path
          description: 'The ID of the product to retrieve operations for.'
          required: true
          schema:
            type: string
      responses:
        200:
          description: 'Successful response'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ProductOperation'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
                  errors:
                    type: array
                    items:
                      type: string
                required:
                  - data
                  - pagination
                  - errors
        401:
          description: Unauthorized
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
  schemas:
    Address:
      type: object
      description: 'Address structure'
      properties:
        assignment:
          type: string
          description: 'Purpose/assignment of the address'
        line1:
          type: string
          description: 'Address line 1 (name/number)'
        line2:
          type: string
          description: 'Address line 2 (street)'
        line3:
          type: string
          description: 'Address line 3 (locality)'
        town:
          type: string
          description: Town/city
        postcode:
          type: string
          description: 'Postal code'
        country:
          type: string
          description: Country
      required:
        - assignment
        - line1
        - line2
        - line3
        - town
        - postcode
        - country
    Contact:
      type: object
      description: 'Contact method structure'
      properties:
        assignment:
          type: string
          description: 'Purpose/assignment of the contact method'
        method:
          type: string
          description: 'Contact method type'
        value:
          type: string
          description: 'Contact value/details'
      required:
        - assignment
        - method
        - value
    Holding:
      type: object
      description: 'Share holding structure'
      properties:
        class:
          type: string
          description: 'Share class'
        quantity:
          type: integer
          description: 'Quantity of shares'
        currency:
          type: string
          description: 'Currency code'
        price:
          type: string
          description: 'Price per share (up to 6 decimal places)'
          pattern: '^[0-9]+\.[0-9]{1,6}$|^$'
      required:
        - class
        - quantity
        - currency
        - price
    NatureOfControl:
      type: object
      description: 'Person with Significant Control (PSC) nature of control'
      properties:
        name:
          type: string
          description: 'Question name'
        description:
          type: string
          description: 'Question description'
        answer:
          type: string
          description: 'Answer to the question'
      required:
        - name
        - description
        - answer
    User:
      type: object
      description: 'Full user resource with contacts and addresses'
      properties:
        id:
          type: string
          description: 'User ID'
        createdAt:
          type: string
          description: 'Creation timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        updatedAt:
          type: string
          description: 'Update timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        username:
          type: string
          description: Username
        organisation:
          type: string
          description: 'Organisation name'
        title:
          type: string
          description: 'User title'
        firstName:
          type: string
          description: 'First name'
        lastName:
          type: string
          description: 'Last name'
        dob:
          type: string
          description: 'Date of birth (YmdHis format, 14 chars padded with zeros). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        creditLimit:
          type: string
          description: 'Credit limit as string to avoid precision loss'
        newsletterSubscribed:
          type: boolean
          description: 'Whether user is subscribed to newsletter'
        contacts:
          type: array
          description: 'User contact methods'
          items:
            $ref: '#/components/schemas/Contact'
        addresses:
          type: array
          description: 'User addresses'
          items:
            $ref: '#/components/schemas/Address'
      required:
        - id
        - createdAt
        - updatedAt
        - username
        - organisation
        - title
        - firstName
        - lastName
        - dob
        - creditLimit
        - newsletterSubscribed
        - contacts
        - addresses
    UserList:
      type: object
      description: 'Simplified user resource for list views'
      properties:
        id:
          type: string
          description: 'User ID'
        createdAt:
          type: string
          description: 'Creation timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        updatedAt:
          type: string
          description: 'Update timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        username:
          type: string
          description: Username
        organisation:
          type: string
          description: 'Organisation name'
        title:
          type: string
          description: 'User title'
        firstName:
          type: string
          description: 'First name'
        lastName:
          type: string
          description: 'Last name'
        dob:
          type: string
          description: 'Date of birth (YmdHis format, 14 chars padded with zeros). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        creditLimit:
          type: string
          description: 'Credit limit as string to avoid precision loss'
        newsletterSubscribed:
          type: boolean
          description: 'Whether user is subscribed to newsletter'
      required:
        - id
        - createdAt
        - updatedAt
        - username
        - organisation
        - title
        - firstName
        - lastName
        - dob
        - creditLimit
        - newsletterSubscribed
    UserCreateUpdate:
      type: object
      description: 'Create/Update user resource'
      properties:
        username:
          type: string
          description: Username
        organisation:
          type: string
          description: 'Organisation name'
        title:
          type: string
          description: 'User title'
        firstName:
          type: string
          description: 'First name'
        lastName:
          type: string
          description: 'Last name'
        password:
          type: string
          description: Password
        creditLimit:
          type: string
          description: 'Credit limit as string to avoid precision loss'
        newsletterSubscribed:
          type: boolean
          description: 'Subscribed to newsletter'
        dob:
          type: string
          description: 'Date of birth (Ymd format)'
          pattern: '^[0-9]{8}$'
    Order:
      type: object
      description: 'Order resource with user and tracking information'
      properties:
        id:
          type: string
          description: 'Order ID'
        description:
          type: string
          description: 'Order description'
        createdAt:
          type: string
          description: 'Order creation timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        updatedAt:
          type: string
          description: 'Order update timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        invoicedAt:
          type: string
          description: 'Order invoiced timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        cancelledAt:
          type: string
          description: 'Order cancelled timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        status:
          type: integer
          description: 'Order status code'
        mlcStatus:
          type: integer
          description: 'MLC (Multi-Level Commission) status code'
        net:
          type: string
          description: 'Net total as string to avoid precision loss, formatted to 2 decimals. Empty string if not set.'
          pattern: '^[0-9]+\.[0-9]{2}$|^$'
        gross:
          type: string
          description: "Gross total as string to avoid precision loss, formatted to 2 decimals. '0.00' if zero, empty string if not set."
          pattern: '^[0-9]+\.[0-9]{2}$|^$'
        user:
          type: object
          description: 'User who created the order'
          properties:
            id:
              type: string
              description: 'User ID'
            organisation:
              type: string
              description: 'Organisation name'
            title:
              type: string
              description: 'User title'
            firstName:
              type: string
              description: 'User first name'
            lastName:
              type: string
              description: 'User last name'
          required:
            - id
            - organisation
            - title
            - firstName
            - lastName
        trackingCodes:
          type: object
          description: 'Marketing tracking codes for attribution'
          properties:
            utmSource:
              type: string
              description: 'UTM source parameter'
            utmMedium:
              type: string
              description: 'UTM medium parameter'
            utmCampaign:
              type: string
              description: 'UTM campaign parameter'
            utmTerm:
              type: string
              description: 'UTM term parameter'
            utmContent:
              type: string
              description: 'UTM content parameter'
            utmId:
              type: string
              description: 'UTM ID parameter'
            affiliate:
              type: string
              description: 'Affiliate code'
          required:
            - utmSource
            - utmMedium
            - utmCampaign
            - utmTerm
            - utmContent
            - utmId
            - affiliate
      required:
        - id
        - description
        - createdAt
        - updatedAt
        - invoicedAt
        - cancelledAt
        - status
        - mlcStatus
        - net
        - gross
        - user
        - trackingCodes
    OrderLine:
      type: object
      description: 'Order line item with product and incorporation details'
      properties:
        orderId:
          type: string
          description: 'Associated order ID'
        description:
          type: string
          description: 'Line item description'
        quantity:
          type: integer
          description: 'Quantity ordered'
        price:
          type: string
          description: 'Unit price (formatted to 2 decimals)'
          pattern: '^[0-9]+\.[0-9]{2}$|^$'
        tax:
          type: string
          description: 'Tax amount (formatted to 2 decimals)'
          pattern: '^[0-9]+\.[0-9]{2}$|^$'
        product:
          type: object
          properties:
            name:
              type: string
              description: 'Product name'
            isService:
              type: boolean
              description: 'Whether this is a service product'
            isIncorporation:
              type: boolean
              description: 'Whether this is an incorporation product'
            taxable:
              type: boolean
              description: 'Whether this product is taxable'
          required:
            - name
            - isService
            - isIncorporation
            - taxable
        package:
          type: object
          properties:
            name:
              type: string
              description: 'Package name'
          required:
            - name
        incorporation:
          type: object
          properties:
            id:
              type: string
              description: 'Incorporation ID (empty string if not applicable)'
            name:
              type: string
              description: 'Company name'
          required:
            - id
            - name
        officer:
          type: object
          properties:
            corporateName:
              type: string
              description: 'Officer company name'
            firstName:
              type: string
              description: 'Officer first name'
            lastName:
              type: string
              description: 'Officer last name'
          required:
            - corporateName
            - firstName
            - lastName
      required:
        - orderId
        - description
        - quantity
        - price
        - tax
        - product
        - package
        - incorporation
        - officer
    Incorporation:
      type: object
      description: 'Company/incorporation resource with registered office and user details'
      properties:
        id:
          type: string
          description: 'Incorporation ID'
        type:
          type: string
          description: 'Company type code'
        name:
          type: string
          description: 'Company name'
        number:
          type: string
          description: "Company registration number (string to preserve leading zeros, e.g., '0624123')"
        authenticationCode:
          type: string
          description: 'Company authentication code for Companies House'
        incorporated:
          type: string
          description: "Date of incorporation (YmdHis format, 14 chars padded with zeros, e.g., '20020223000000'). Empty string if not set."
          pattern: '^[0-9]{14}$|^$'
        status:
          type: integer
          description: 'Company status code'
        createdAt:
          type: string
          description: 'Record creation timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        updatedAt:
          type: string
          description: 'Record update timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        registeredEmail:
          type: string
          description: 'Company registered email address'
        registeredOffice:
          $ref: '#/components/schemas/Address'
        user:
          type: object
          description: 'User who created/owns this incorporation'
          properties:
            id:
              type: string
              description: 'User ID'
            organisation:
              type: string
              description: 'Organisation name'
            title:
              type: string
              description: 'User title'
            firstName:
              type: string
              description: 'User first name'
            lastName:
              type: string
              description: 'User last name'
          required:
            - id
            - organisation
            - title
            - firstName
            - lastName
      required:
        - id
        - type
        - name
        - number
        - authenticationCode
        - incorporated
        - status
        - createdAt
        - updatedAt
        - registeredEmail
        - registeredOffice
        - user
    IncorporationDates:
      type: object
      description: 'Company important dates and deadlines'
      properties:
        companyNumber:
          type: string
          description: 'Company registration number'
        incorporatedDate:
          type: string
          description: 'Date of incorporation (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        accountsDue:
          type: string
          description: 'Accounts due date (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        cs01Due:
          type: string
          description: 'CS01 confirmation statement due date (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        dissolvedAt:
          type: string
          description: 'Company dissolved date (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        createdAt:
          type: string
          description: 'Record creation timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        updatedAt:
          type: string
          description: 'Record update timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
      required:
        - companyNumber
        - incorporatedDate
        - accountsDue
        - cs01Due
        - dissolvedAt
        - createdAt
        - updatedAt
    IncorporationOfficer:
      type: object
      description: 'Company officer resource with addresses and holdings'
      properties:
        id:
          type: string
          description: 'Officer ID'
        type:
          type: string
          description: 'Officer type (director, secretary, etc.)'
        corporateName:
          type: string
          description: 'Corporate name if officer is a company'
        title:
          type: string
          description: 'Officer title'
        firstName:
          type: string
          description: 'Officer first name'
        lastName:
          type: string
          description: 'Officer last name'
        email:
          type: string
          description: 'Officer email address'
        dob:
          type: string
          description: 'Date of birth (YmdHis format, 14 chars padded with zeros). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        nationality:
          type: string
          description: 'Officer nationality'
        roles:
          type: object
          description: 'Officer roles in the company'
          properties:
            topdog:
              type: boolean
              description: 'Is director'
            secretary:
              type: boolean
              description: 'Is secretary'
            holder:
              type: boolean
              description: 'Is shareholder'
            psc:
              type: boolean
              description: 'Is person with significant control'
          required:
            - topdog
            - secretary
            - holder
            - psc
        residentialAddress:
          $ref: '#/components/schemas/Address'
        serviceAddress:
          $ref: '#/components/schemas/Address'
        holdings:
          type: array
          description: 'Share holdings'
          items:
            $ref: '#/components/schemas/Holding'
        natureOfControl:
          type: array
          description: 'Nature of control statements (for PSC)'
          items:
            $ref: '#/components/schemas/NatureOfControl'
        incorporation:
          type: object
          properties:
            id:
              type: string
              description: 'Incorporation ID'
            name:
              type: string
              description: 'Company name'
            number:
              type: string
              description: 'Company registration number'
            status:
              type: integer
              description: 'Company status code'
          required:
            - id
            - name
            - number
            - status
        user:
          type: object
          properties:
            id:
              type: string
              description: 'User ID'
            organisation:
              type: string
              description: 'Organisation name'
            title:
              type: string
              description: 'User title'
            firstName:
              type: string
              description: 'User first name'
            lastName:
              type: string
              description: 'User last name'
          required:
            - id
            - organisation
            - title
            - firstName
            - lastName
      required:
        - id
        - type
        - corporateName
        - title
        - firstName
        - lastName
        - email
        - dob
        - nationality
        - roles
        - residentialAddress
        - serviceAddress
        - holdings
        - natureOfControl
        - incorporation
        - user
    Service:
      type: object
      description: 'Service subscription resource with incorporation, officer, orderline and user details'
      properties:
        id:
          type: string
          description: 'Service ID'
        autoRenew:
          type: boolean
          description: 'Whether service automatically renews'
        renewDate:
          type: string
          description: 'Next renewal date (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        createdAt:
          type: string
          description: 'Creation timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        updatedAt:
          type: string
          description: 'Update timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        cancelledAt:
          type: string
          description: 'Cancellation timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        cancelledBy:
          type: string
          description: 'ID of user who cancelled the service. Empty string if not set.'
        status:
          type: integer
          description: 'Service status code'
        statusText:
          type: string
          description: 'Human-readable service status'
        incorporation:
          type: object
          description: 'Associated incorporation summary'
          properties:
            id:
              type: string
              description: 'Incorporation ID. Empty string if not set.'
            name:
              type: string
              description: 'Company name'
            number:
              type: string
              description: 'Company number'
          required:
            - id
            - name
            - number
        officer:
          type: object
          description: 'Associated officer details'
          properties:
            id:
              type: string
              description: 'Officer ID. Empty string if not set.'
            type:
              type: string
              description: 'Officer type'
            corporateName:
              type: string
              description: 'Corporate name if applicable'
            firstName:
              type: string
              description: 'Officer first name'
            lastName:
              type: string
              description: 'Officer last name'
            email:
              type: string
              description: 'Officer email address'
            dob:
              type: string
              description: 'Date of birth (YmdHis format, 14 chars padded with zeros). Empty string if not set.'
              pattern: '^[0-9]{14}$|^$'
          required:
            - id
            - type
            - corporateName
            - firstName
            - lastName
            - email
            - dob
        orderline:
          type: object
          description: 'Associated order line with product details'
          properties:
            orderId:
              type: string
              description: 'Order ID. Empty string if not set.'
            product:
              type: object
              description: 'Associated product details'
              properties:
                id:
                  type: string
                  description: 'Product ID. Empty string if not set.'
                name:
                  type: string
                  description: 'Product name'
              required:
                - id
                - name
          required:
            - orderId
            - product
        user:
          type: object
          description: 'Service owner user details'
          properties:
            id:
              type: string
              description: 'User ID. Empty string if not set.'
            organisation:
              type: string
              description: 'Organisation name'
            firstName:
              type: string
              description: 'User first name'
            lastName:
              type: string
              description: 'User last name'
            dob:
              type: string
              description: 'Date of birth'
            email:
              type: string
              description: 'Email address'
            phone:
              type: string
              description: 'Phone number'
            accountBalance:
              type: string
              description: 'Account balance as string to avoid precision loss'
            storedCard:
              type: boolean
              description: 'Whether user has a stored payment card'
          required:
            - id
            - organisation
            - firstName
            - lastName
            - dob
            - email
            - phone
            - accountBalance
            - storedCard
      required:
        - id
        - autoRenew
        - renewDate
        - createdAt
        - updatedAt
        - cancelledAt
        - cancelledBy
        - status
        - statusText
        - incorporation
        - officer
        - orderline
        - user
    ServiceItem:
      type: object
      description: 'Service item/task resource'
      properties:
        id:
          type: string
          description: 'Service item ID'
        serviceId:
          type: string
          description: 'Associated service ID. Empty string if not set.'
        operationId:
          type: string
          description: 'Associated operation ID. Empty string if not set.'
        userId:
          type: string
          description: 'Associated user ID. Empty string if not set.'
        incorporationId:
          type: string
          description: 'Associated incorporation ID. Empty string if not set.'
        officerId:
          type: string
          description: 'Associated officer ID. Empty string if not set.'
        status:
          type: integer
          description: 'Item status code'
        price:
          type: string
          description: 'Item price (formatted to 2 decimals)'
          pattern: '^[0-9]+\.[0-9]{2}$|^$'
        description:
          type: string
          description: 'Item description'
        externalRef:
          type: string
          description: 'External reference number'
        createdAt:
          type: string
          description: 'Creation timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        updatedAt:
          type: string
          description: 'Update timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
      required:
        - id
        - serviceId
        - operationId
        - userId
        - incorporationId
        - officerId
        - status
        - price
        - description
        - externalRef
        - createdAt
        - updatedAt
    ServiceItemCreateUpdate:
      type: object
      description: 'Create service item request'
      properties:
        operationId:
          type: string
          description: 'Associated operation ID'
        incorporationId:
          type: string
          description: 'Associated incorporation ID (optional)'
        officerId:
          type: string
          description: 'Associated officer ID (optional)'
        status:
          type: integer
          description: 'Item status code (optional)'
        price:
          type: string
          description: 'Item price (formatted to 2 decimals, optional)'
          pattern: '^[0-9]+\.[0-9]{2}$|^$'
        description:
          type: string
          description: 'Item description'
        externalRef:
          type: string
          description: 'External reference number (optional)'
      required:
        - operationId
        - description
    ProductOperation:
      type: object
      description: 'Product operation/add-on resource'
      properties:
        id:
          type: string
          description: 'Operation ID'
        name:
          type: string
          description: 'Operation name'
        productId:
          type: string
          description: 'Associated product ID'
        price:
          type: string
          description: 'Operation price (formatted to 2 decimals)'
          pattern: '^[0-9]+\.[0-9]{2}$|^$'
      required:
        - id
        - name
        - productId
        - price
    Product:
      type: object
      description: 'Product resource'
      properties:
        id:
          type: string
          description: 'Product ID'
        name:
          type: string
          description: 'Product name'
        description:
          type: string
          description: 'Product description'
        price:
          type: string
          description: "Product price (formatted to 2 decimals). Defaults to '0.00' if not set."
          pattern: '^[0-9]+\.[0-9]{2}$|^$'
        type:
          type: string
          description: "Product type (e.g., 'REGOFFICE', 'MAILFORWARD', etc.). Defaults to 'STANDARD' if not set."
        status:
          type: integer
          description: 'Product status code'
        taxable:
          type: boolean
          description: 'Whether the product is taxable'
        isService:
          type: boolean
          description: 'Whether the product is a service'
        autoRenew:
          type: boolean
          description: 'Whether the product auto-renews'
        createdAt:
          type: string
          description: 'Creation timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        updatedAt:
          type: string
          description: 'Update timestamp (YmdHis format, 14 chars). Empty string if not set.'
          pattern: '^[0-9]{14}$|^$'
        user:
          type: object
          description: 'Associated user details'
          properties:
            id:
              type: string
              description: 'User ID. Empty string if not set.'
          required:
            - id
      required:
        - id
        - name
        - description
        - price
        - type
        - status
        - taxable
        - isService
        - autoRenew
        - createdAt
        - updatedAt
        - user
    Pagination:
      type: object
      description: 'Page-based pagination metadata'
      properties:
        resultCount:
          type: integer
          description: 'Number of results in current page'
        resultTotal:
          type: integer
          description: 'Total number of results'
        currentPage:
          type: integer
          description: 'Current page number'
        totalPages:
          type: integer
          description: 'Total number of pages'
      required:
        - resultCount
        - resultTotal
        - currentPage
        - totalPages
    PaginationCursor:
      type: object
      description: 'Cursor-based pagination metadata'
      properties:
        cursor:
          type: string
          description: 'Cursor for the next page of results'
        resultCount:
          type: integer
          description: 'Number of results in current page'
        resultTotal:
          type: integer
          description: 'Total number of results'
      required:
        - cursor
        - resultCount
        - resultTotal
security:
  -
    ApiKeyAuth: {  }
