openapi: 3.0.3
info:
  title: RunMyAccount Proxy API
  version: 1.0.0
  description: |
    Authenticated HTTP proxy for RunMyAccount customers and invoices.
    Clients authenticate with `PROXY_API_TOKEN`. The RunMyAccount API key
    stays on the server and is never returned.
servers:
  - url: http://localhost:3020
    description: Local development
  - url: https://{vercelDeploymentHost}
    description: Vercel deployment (Root Directory apps/runmyaccount-api)
    variables:
      vercelDeploymentHost:
        default: example.vercel.app
security:
  - BearerAuth: []
paths:
  /health:
    get:
      security: []
      summary: Health check
      operationId: getHealth
      responses:
        "200":
          description: Service is up
          content:
            application/json:
              schema:
                type: object
                required: [ok]
                properties:
                  ok:
                    type: boolean
                    example: true
  /api/v1/customers:
    get:
      summary: List customers
      operationId: listCustomers
      parameters:
        - $ref: "#/components/parameters/PassthroughQuery"
      responses:
        "200":
          description: Customer list from upstream
          content:
            application/json:
              schema:
                oneOf:
                  - type: array
                    items:
                      $ref: "#/components/schemas/Customer"
                  - type: object
                    additionalProperties: true
        "401":
          $ref: "#/components/responses/Unauthorized"
    post:
      summary: Create customer
      operationId: createCustomer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateCustomerRequest"
            example:
              customernumber: NAMBKD-00099
              name: Otto Client
              email: otto@example.com
              address1: Teststrasse 1
              zipcode: "8000"
              city: Zürich
              country: Switzerland
              typeofcontact: person
              terms: 30
      responses:
        "201":
          description: Created (upstream status may vary among 2xx)
        "401":
          $ref: "#/components/responses/Unauthorized"
  /api/v1/customers/{customernumber}:
    get:
      summary: Get customer by number
      operationId: getCustomer
      parameters:
        - name: customernumber
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Customer
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Customer"
        "401":
          $ref: "#/components/responses/Unauthorized"
  /api/v1/invoices:
    get:
      summary: List invoices
      operationId: listInvoices
      parameters:
        - $ref: "#/components/parameters/ApiVersion"
        - $ref: "#/components/parameters/PassthroughQuery"
      responses:
        "200":
          description: Invoice list from upstream
          content:
            application/json:
              schema:
                oneOf:
                  - type: array
                    items:
                      $ref: "#/components/schemas/Invoice"
                  - type: object
                    additionalProperties: true
        "401":
          $ref: "#/components/responses/Unauthorized"
    post:
      summary: Create invoice
      operationId: createInvoice
      parameters:
        - $ref: "#/components/parameters/ApiVersion"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateInvoiceRequest"
      responses:
        "201":
          description: Created (upstream status may vary among 2xx)
        "401":
          $ref: "#/components/responses/Unauthorized"
  /api/v1/invoices/{invoice_number}:
    get:
      summary: Get invoice (payment status)
      operationId: getInvoice
      parameters:
        - name: invoice_number
          in: path
          required: true
          schema:
            type: string
        - $ref: "#/components/parameters/ApiVersion"
      responses:
        "200":
          description: Invoice including payment-related fields
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Invoice"
        "401":
          $ref: "#/components/responses/Unauthorized"
  /api/v1/invoices/{invoice_number}/pdf:
    get:
      summary: Get invoice PDF
      operationId: getInvoicePdf
      parameters:
        - name: invoice_number
          in: path
          required: true
          schema:
            type: string
        - $ref: "#/components/parameters/ApiVersion"
        - name: languageCode
          in: query
          schema:
            type: string
          description: Forwarded upstream (e.g. inkl)
        - name: formname
          in: query
          schema:
            type: string
          description: Forwarded upstream (e.g. reminder3)
      responses:
        "200":
          description: PDF binary
          content:
            application/pdf:
              schema:
                type: string
                format: binary
        "401":
          $ref: "#/components/responses/Unauthorized"
  /api/v1/invoices/{invoice_number}/html:
    get:
      summary: Get invoice HTML
      operationId: getInvoiceHtml
      parameters:
        - name: invoice_number
          in: path
          required: true
          schema:
            type: string
        - $ref: "#/components/parameters/ApiVersion"
      responses:
        "200":
          description: HTML document
          content:
            text/html:
              schema:
                type: string
        "401":
          $ref: "#/components/responses/Unauthorized"
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: Value of PROXY_API_TOKEN from the proxy server env
  parameters:
    ApiVersion:
      name: version
      in: query
      required: false
      schema:
        type: string
        example: latest
      description: |
        Rewrites upstream `/api/{version}/` segment. Consumed by the proxy;
        not forwarded as a query parameter.
    PassthroughQuery:
      name: q
      in: query
      required: false
      schema:
        type: string
      description: Example passthrough query; any other query params are forwarded
  responses:
    Unauthorized:
      description: Missing or invalid bearer token
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/UnauthorizedError"
  schemas:
    UnauthorizedError:
      type: object
      required: [error, message]
      properties:
        error:
          type: string
          example: unauthorized
        message:
          type: string
          example: Missing or invalid Authorization bearer token
    Customer:
      type: object
      required: [customernumber, name]
      properties:
        id:
          type: string
        customernumber:
          type: string
        name:
          type: string
        email:
          type: string
        address1:
          type: string
        zipcode:
          type: string
        city:
          type: string
        firstname:
          type: string
        lastname:
          type: string
        phone:
          type: string
        country:
          type: string
        typeofcontact:
          type: string
        salutation:
          type: string
        gender:
          type: string
        notes:
          type: string
        terms:
          oneOf:
            - type: string
            - type: number
      additionalProperties: true
    CreateCustomerRequest:
      type: object
      required: [customernumber, name]
      properties:
        customernumber:
          type: string
        name:
          type: string
        created:
          type: string
          format: date-time
        firstname:
          type: string
        lastname:
          type: string
        address1:
          type: string
        zipcode:
          type: string
        city:
          type: string
        country:
          type: string
        phone:
          type: string
        email:
          type: string
        salutation:
          type: string
        typeofcontact:
          type: string
        notes:
          type: string
        terms:
          oneOf:
            - type: string
            - type: number
        tax_accnos:
          type: string
        gender:
          type: string
      additionalProperties: true
    InvoicePart:
      type: object
      properties:
        partnumber:
          type: string
        description:
          type: string
        quantity:
          type: string
        sellprice:
          type: string
        discount:
          type: string
      additionalProperties: true
    Invoice:
      type: object
      required: [invnumber, status, amount]
      description: |
        Payment status fields of interest: status, paid, amount, duedate.
      properties:
        id:
          type: string
        invnumber:
          type: string
        status:
          type: string
          description: Invoice / payment status
        amount:
          type: string
        netamount:
          type: string
        paid:
          type: string
          description: Amount paid so far
        transdate:
          type: string
          format: date-time
        duedate:
          type: string
          format: date-time
        description:
          type: string
        notes:
          type: string
        currency:
          type: string
        customer:
          $ref: "#/components/schemas/Customer"
        parts:
          type: object
          properties:
            part:
              oneOf:
                - $ref: "#/components/schemas/InvoicePart"
                - type: array
                  items:
                    $ref: "#/components/schemas/InvoicePart"
        payment_accno:
          type: string
        ar_accno:
          type: string
      additionalProperties: true
    CreateInvoiceRequest:
      type: object
      required: [customernumber, invnumber, transdate, duedate, parts]
      properties:
        customernumber:
          type: string
        invnumber:
          type: string
        transdate:
          type: string
          format: date-time
        duedate:
          type: string
          format: date-time
        description:
          type: string
        notes:
          type: string
        payment_accno:
          type: string
          example: "1020"
        ar_accno:
          type: string
          example: "1100"
        dcn:
          type: string
        parts:
          type: object
          required: [part]
          properties:
            part:
              oneOf:
                - $ref: "#/components/schemas/InvoicePart"
                - type: array
                  items:
                    $ref: "#/components/schemas/InvoicePart"
      additionalProperties: true
