# UTF-8. English descriptions only; same paths/schemas as einvoice-api-openapi.yaml.
# Keep in sync with the Chinese file on contract changes.
openapi: 3.0.3
info:
  title: e首發票 API
  description: |
    e首發票 Taiwan e-invoice center APIs: issue invoice (invoice mode: numbers allocated by taxpayer, then submit),
    void invoice, and issue electronic invoice allowance (credit note).
    Typical channels: e-commerce, ERP, POS, kiosks / payment devices. Numbering strategy: see scenario docs (invoice mode vs order mode).
  version: "2025.03"
  contact:
    name: e首發票服務
  license:
    name: Per service agreement

servers:
  - url: https://webapi.systemlead.com/terpapi
    description: Test environment (confirm actual URLs with your service provider)
  - url: https://webapi.systemlead.com/terpapi
    description: Production environment (URL per contract)

tags:
  - name: Issue
    description: Invoice-mode issuance (submit after taxpayer-side numbering)
  - name: Void
    description: Void issued invoices
  - name: Allowance
    description: Allowance (credit note) for e-invoices

paths:
  /Append/Invoices:
    post:
      tags: [Issue]
      summary: Issue invoice (invoice mode)
      description: |
        Invoice mode: after your system allocates invoice numbers, submit issuance payload in JSON.
        - Request/response: JSON
        - Signature: SHA256 (GUI + secret key + timestamp); respect expiry; do not reuse timestamps.
        - Filing windows: C-type 48 hours, B-type 7 days to upload per MOF rules — confirm current guidance.
      operationId: appendInvoices
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/InvoiceIssueRequest"
            examples:
              B2B:
                $ref: "#/components/examples/B2BInvoice"
              B2C:
                $ref: "#/components/examples/B2CInvoice"
      responses:
        "200":
          description: Issue result (success or failure returned in body)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InvoiceIssueResponse"
        "4xx":
          description: Client error or signature verification failure
        "5xx":
          description: Server error

  /Update/CancelInvoices:
    post:
      tags: [Void]
      summary: Void invoice(s)
      description: |
        Void issued invoice(s). Supports single object or batch (Data as array).
        - Signature: SHA256
      operationId: cancelInvoices
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CancelInvoiceRequest"
      responses:
        "200":
          description: Void result (single or array)
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/CancelInvoiceResponse"
                  - type: array
                    items:
                      $ref: "#/components/schemas/CancelInvoiceResponse"

  /Update/AllowanceInvoice:
    post:
      tags: [Allowance]
      summary: Allowance (credit note) for e-invoice
      description: |
        Create an allowance for a B2B/B2C e-invoice. Taxable / exempt / zero-rate / mixed tax rules apply
        (mixed tax C-type only; typically one taxable and one exempt line pattern per provider rules).
        - Totals and tax must pass validation (e.g. 5% VAT rounding for taxable lines).
      operationId: allowanceInvoice
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AllowanceInvoiceRequest"
      responses:
        "200":
          description: Allowance result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AllowanceInvoiceResponse"

components:
  securitySchemes:
    SignatureInBody:
      type: apiKey
      in: header
      name: X-API-Key
      description: |
        Real verification uses JSON body fields CompanyID, Timestamp, Signature (SHA256).
        Computation uses seller GUI (8 digits), secret key, and timestamp; respect expiry; avoid duplicate timestamps.
        Header key in Swagger is illustrative; follow your provider's body-signature specification in production.

  schemas:
    SignedPayload:
      type: object
      required:
        - CompanyID
        - Timestamp
        - Signature
      properties:
        CompanyID:
          type: string
          maxLength: 8
          description: Seller GUI (Taiwan uniform invoice title ID, 8 digits)
        Timestamp:
          type: string
          description: Time token used in signature; expires; do not reuse across submissions
        Signature:
          type: string
          description: SHA256 signature (hex or provider format)

    InvoiceIssueRequest:
      allOf:
        - $ref: "#/components/schemas/SignedPayload"
        - type: object
          required: [Data]
          properties:
            Data:
              $ref: "#/components/schemas/InvoiceData"

    InvoiceData:
      type: object
      required:
        - InvoiceID
        - InvoiceDateTime
        - InvoiceFor
        - BuyerID
        - BuyerName
        - BuyerEmailAddress
        - TaxType
        - SalesAmount
        - TaxAmount
        - TotalAmount
        - Details
      properties:
        InvoiceID:
          type: string
          maxLength: 10
          description: Full invoice number (letters + digits); batch submissions to avoid duplicates
        InvoiceDateTime:
          type: string
          format: date-time
          example: "2025-03-17T19:43:37"
          description: Issue date-time, YYYY-MM-DDTHH:mm:ss
        BillingNo:
          type: string
          maxLength: 30
          description: Order / billing reference; must be unique
        InvoiceFor:
          type: string
          enum: [B, C]
          description: "B=B2B, C=B2C"
        BuyerID:
          type: string
          maxLength: 10
          description: Buyer GUI; use 0000000000 for B2C
        BuyerInvoiceTitle:
          type: string
          maxLength: 60
          description: Buyer invoice title; required for B2B
        BuyerName:
          type: string
          maxLength: 60
          description: Buyer display name
        BuyerTelNo:
          type: string
          maxLength: 26
          description: Buyer phone (e.g. SMS notifications)
        BuyerEmailAddress:
          type: string
          maxLength: 80
          description: Buyer email; invalid format may be cleared and may affect allow/block lists
        CheckNumber:
          type: string
          maxLength: 4
          description: Invoice check code; B2C often 9999
        RandomNumber:
          type: string
          maxLength: 4
          description: Random code on invoice; B2C often 9999
        PrintMark:
          type: string
          enum: [Y, N]
          description: C-type proof copy printed flag
        TaxType:
          type: string
          enum: ["1", "2", "3", "9"]
          description: "1=taxable, 2=zero-rate, 3=exempt, 9=mixed (C-type only)"
        SalesAmount:
          type: integer
          description: Taxable sales amount (integer, rounded)
        FreeTaxSalesAmount:
          type: integer
          default: 0
        ZeroTaxSalesAmount:
          type: integer
          default: 0
        TaxAmount:
          type: integer
          description: VAT amount; B-type ~5% of taxable sales rounded; C-type 0
        TotalAmount:
          type: integer
          description: Grand total (tax-inclusive rules per B/C)
        CarrierType:
          type: string
          example: "3J0002"
          description: Carrier type code (e.g. mobile barcode)
        CarrierId:
          type: string
          maxLength: 64
          description: Carrier id; mobile barcode often "/" + 7 digits
        NPOBAN:
          type: string
          minLength: 3
          maxLength: 10
          description: Donation NPO GUI (love code)
        Note:
          type: string
          maxLength: 250
          description: System note; may include cc*email*cc pattern for CC recipients
        Details:
          type: array
          items:
            $ref: "#/components/schemas/InvoiceDetailItem"

    InvoiceDetailItem:
      type: object
      required:
        - DetailID
        - ProductName
        - Quantity
        - UnitPrice
        - SubTotal
        - ItemTaxType
      properties:
        DetailID:
          type: string
          maxLength: 4
          example: "0001"
        ProductName:
          type: string
          maxLength: 256
        Quantity:
          type: number
          format: double
        UnitPrice:
          type: number
          format: double
        SubTotal:
          type: number
          format: double
          description: Quantity × UnitPrice
        ItemTaxType:
          type: string
          enum: ["1", "2", "3"]
          description: "1=taxable, 2=zero-rate, 3=exempt"

    InvoiceIssueResponse:
      type: object
      properties:
        InvoiceID:
          type: string
        InvoiceNumber:
          type: string
        InvoiceDateTime:
          type: string
          format: date-time
        StatusCode:
          type: integer
          description: "1=success, 0=failure"
        ResultMessage:
          type: string
          description: Success or error text — handle failures to avoid missed issuance

    CancelInvoiceRequest:
      allOf:
        - $ref: "#/components/schemas/SignedPayload"
        - type: object
          required: [Data]
          properties:
            Data:
              oneOf:
                - $ref: "#/components/schemas/CancelInvoiceData"
                - type: array
                  items:
                    $ref: "#/components/schemas/CancelInvoiceData"

    CancelInvoiceData:
      type: object
      required:
        - SellerID
        - InvoiceNumber
        - CancelDate
        - CancelReason
      properties:
        SellerID:
          type: string
          maxLength: 8
        InvoiceNumber:
          type: string
          maxLength: 10
          description: Invoice number to void
        CancelDate:
          type: string
          format: date-time
          example: "2024-12-13T14:30:00"
        CancelReason:
          type: string
          maxLength: 20
          description: Reason text, e.g. return, order cancelled

    CancelInvoiceResponse:
      type: object
      properties:
        SellerID:
          type: string
        InvoiceNumber:
          type: string
        StatusCode:
          type: integer
          description: "1=success, 0=failure"
        ResultMessage:
          type: string

    AllowanceInvoiceRequest:
      allOf:
        - $ref: "#/components/schemas/SignedPayload"
        - type: object
          required: [Data]
          properties:
            Data:
              $ref: "#/components/schemas/AllowanceData"

    AllowanceData:
      type: object
      required:
        - AllowanceNumberPrefix
        - SellerID
        - BuyerID
        - AllowanceType
        - TaxAmount
        - TotalAmount
        - Details
      properties:
        AllowanceNumberPrefix:
          type: string
          maxLength: 16
          description: Allowance document id prefix; must be unique; time-based serial recommended
        SellerID:
          type: string
          maxLength: 8
        BuyerID:
          type: string
          maxLength: 10
          description: B2B buyer GUI; B2C use 0000000000
        AllowanceType:
          type: string
          enum: ["2"]
          description: Fixed 2 (seller-issued allowance)
        TaxAmount:
          type: number
          description: Allowance VAT total; sum of taxable line taxes
        TotalAmount:
          type: number
          description: Allowance grand total; sum of line amounts
        Details:
          type: array
          items:
            $ref: "#/components/schemas/AllowanceDetailItem"

    AllowanceDetailItem:
      type: object
      required:
        - InvoiceNumber
        - SequenceNumber
        - Amount
        - Quantity
        - UnitPrice
        - ItemTaxType
        - Tax
      properties:
        InvoiceNumber:
          type: string
          maxLength: 10
          description: Original invoice number (track + 8 digits)
        SequenceNumber:
          type: string
          maxLength: 4
          example: "0001"
        Amount:
          type: number
        Quantity:
          type: number
        UnitPrice:
          type: number
        ItemTaxType:
          type: string
          enum: ["1", "2", "3"]
        Tax:
          type: number
          description: For ItemTaxType=1, typically Amount×0.05 rounded

    AllowanceInvoiceResponse:
      type: object
      properties:
        SellerID:
          type: string
        AllowanceNumber:
          type: string
        StatusCode:
          type: integer
          description: "1=success, 0=failure"
        ResultMessage:
          type: string

  examples:
    B2BInvoice:
      value:
        CompanyID: "12345678"
        Timestamp: "1677585655"
        Signature: "4754A5FE41749DE99E82FC5502348C69781E1026064ADF7AC"
        Data:
          InvoiceID: "NX25780488"
          InvoiceDateTime: "2025-03-17T19:43:37"
          InvoiceFor: "B"
          BuyerID: "87654321"
          BuyerName: "企業買家"
          BuyerEmailAddress: "einv@einv.tw"
          TaxType: "1"
          SalesAmount: 5000
          FreeTaxSalesAmount: 0
          ZeroTaxSalesAmount: 0
          TaxAmount: 250
          TotalAmount: 5250
          Details:
            - DetailID: "001"
              ProductName: "商品A"
              ItemTaxType: "1"
              Quantity: 1
              UnitPrice: 5000
              SubTotal: 5000
    B2CInvoice:
      value:
        CompanyID: "12345678"
        Timestamp: "1677585655"
        Signature: "4754A5FE41749DE99E82FC5502348C69781E1026064ADF7AC"
        Data:
          InvoiceID: "NX25780489"
          InvoiceDateTime: "2025-03-17T19:45:00"
          InvoiceFor: "C"
          BuyerID: "0000000000"
          BuyerEmailAddress: "einv@einv.tw"
          TaxType: "1"
          SalesAmount: 2000
          FreeTaxSalesAmount: 0
          ZeroTaxSalesAmount: 0
          TaxAmount: 0
          TotalAmount: 2000
          Details:
            - DetailID: "001"
              ProductName: "商品B"
              ItemTaxType: "1"
              Quantity: 1
              UnitPrice: 2000
              SubTotal: 2000
