openapi: 3.0.3
info:
  title: Logi Open API
  version: 1.0.0
  description: >-
    Logi canonical Open API contract plus implemented compatibility adapters.
    Runtime availability still depends on deployment credentials and readiness gates.
servers:
  - url: http://localhost:9100
paths:
  /api/v1/capabilities:
    get:
      summary: List canonical and compatibility protocol capabilities
      security: []
      responses:
        '200':
          description: Capability declaration. DESIGNING operations are not callable.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CapabilityResponse'
  /api/v1/orders:
    post:
      summary: Create one shipment through the canonical Logi order core
      parameters:
        - $ref: '#/components/parameters/AccessKey'
        - $ref: '#/components/parameters/Timestamp'
        - $ref: '#/components/parameters/Signature'
        - $ref: '#/components/parameters/IdempotencyKey'
        - $ref: '#/components/parameters/RequestId'
        - $ref: '#/components/parameters/TraceId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateOrderRequest'
      responses:
        '200':
          description: Order accepted by the real shared order core.
          headers:
            X-Logi-Request-Id:
              schema: { type: string }
            X-Logi-Trace-Id:
              schema: { type: string }
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderAcceptedEnvelope'
        '401':
          description: Authentication, timestamp, IP whitelist or rate-limit rejection.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '403':
          description: Product or channel is not authorized for the authenticated customer.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '422':
          description: Invalid JSON, fields, address, product readiness or business rule.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '503':
          description: A shared internal service is temporarily unavailable.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
  /compat/hualei/{accessKey}/selectAuth.htm:
    post:
      summary: Exchange a dedicated Hualei compatibility username/password for a short-lived token
      description: >-
        CONTROLLED_PREVIEW. The password is accepted as form data and is verified against a BCrypt
        hash. The returned token is never a provider credential and expires after 900 seconds.
      x-logi-lifecycle: CONTROLLED_PREVIEW
      security: []
      parameters:
        - name: accessKey
          in: path
          required: true
          description: System-generated customer access identifier contained in the assigned base URL.
          schema: { type: string, pattern: '^hl_[A-Z2-9]{12}$' }
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              required: [username, password]
              properties:
                username: { type: string }
                password: { type: string, format: password, writeOnly: true }
      responses:
        '200':
          description: Hualei ack envelope. Authentication failure also uses ack=false.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HualeiAck'
  /compat/hualei/{accessKey}/getProductList.htm:
    get:
      summary: List enabled Hualei product IDs assigned to this customer
      x-logi-lifecycle: CONTROLLED_PREVIEW
      security: []
      parameters:
        - name: accessKey
          in: path
          required: true
          schema: { type: string, pattern: '^hl_[A-Z2-9]{12}$' }
      responses:
        '200':
          description: Original Hualei bare product array; failures return an ack=false object.
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  required: [product_id, product_shortname]
                  properties:
                    product_id: { type: string }
                    product_shortname: { type: string }
  /compat/hualei/{accessKey}/createOrderApi.htm:
    post:
      summary: Create one shipment through the Hualei param/ack compatibility adapter
      description: >-
        Supports the original fixed-IP session established by selectAuth.htm, or the enhanced
        short-lived compatibility token, timestamp and unique nonce mode.
        ack=true is returned only after customer-scoped product alias resolution, shared channel guards
        and the real Logi Order core accept the request.
      x-logi-lifecycle: CONTROLLED_PREVIEW
      security: []
      parameters:
        - name: accessKey
          in: path
          required: true
          description: Customer scope generated together with the Hualei account.
          schema: { type: string, pattern: '^hl_[A-Z2-9]{12}$' }
        - name: X-Logi-Compat-Token
          in: header
          required: false
          description: Required with the enhanced mode; omit all three compatibility headers for original fixed-IP session mode.
          schema: { type: string }
        - name: X-Logi-Compat-Timestamp
          in: header
          required: false
          description: Unix epoch milliseconds; current window is 300 seconds.
          schema: { type: string, pattern: '^[0-9]{13}$' }
        - name: X-Logi-Compat-Nonce
          in: header
          required: false
          description: Unique per token request; exact replays are atomically rejected.
          schema: { type: string, pattern: '^[A-Za-z0-9._:-]{8,128}$' }
        - $ref: '#/components/parameters/RequestId'
        - $ref: '#/components/parameters/TraceId'
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              required: [param]
              properties:
                param:
                  type: string
                  description: UTF-8 JSON containing documented Hualei order fields.
      responses:
        '200':
          description: Hualei ack envelope. Any auth, mapping, guard or core failure uses ack=false.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HualeiAck'
  /compat/hualei-print/{accessKey}/order/FastRpt/PDF_NEW.aspx:
    get:
      summary: Download the archived real PDF label through the Hualei print base URL
      description: >-
        The customer's Hualei-compatible system appends this fixed path to the assigned print base URL.
        Success requires an owned order and a validated archived PDF; no placeholder PDF is generated.
      x-logi-lifecycle: CONTROLLED_PREVIEW
      security: []
      parameters:
        - name: accessKey
          in: path
          required: true
          schema: { type: string, pattern: '^hl_[A-Z2-9]{12}$' }
        - name: PrintType
          in: query
          required: false
          schema: { type: string, default: lab10_10 }
        - name: order_id
          in: query
          required: true
          schema: { type: string }
      responses:
        '200':
          description: Validated PDF label bytes.
          content:
            application/pdf:
              schema: { type: string, format: binary }
  /compat/cluan/openapi/v1/channel/list:
    post:
      summary: List customer-authorized products through the Cluan-compatible contract
      security: []
      parameters:
        - $ref: '#/components/parameters/CluanApiKey'
        - $ref: '#/components/parameters/CluanAuthorization'
        - $ref: '#/components/parameters/CluanTimeStamp'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CluanEmptyDataRequest'
      responses:
        '200':
          description: Cluan-compatible response; runtime use requires deployment readiness.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CluanResponse'
  /compat/cluan/openapi/v1/basic/order/create:
    post:
      summary: Create one order through the Cluan-compatible signed raw-body contract
      description: >-
        The signature URI is /openapi/v1/basic/order/create. Success is returned only when
        the shared channel guard and Order core return a real Logi order number.
      security: []
      parameters:
        - $ref: '#/components/parameters/CluanApiKey'
        - $ref: '#/components/parameters/CluanAuthorization'
        - $ref: '#/components/parameters/CluanTimeStamp'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CluanCreateOrderRequest'
      responses:
        '200':
          description: Cluan-compatible result. No placeholder tracking number or label is generated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CluanResponse'
  /compat/cluan/openapi/v1/tracking/list:
    post:
      summary: Query verified tracking evidence through the Cluan-compatible contract
      description: >-
        The signature URI is /openapi/v1/tracking/list. trackingType and the documented
        example alias trackType are accepted individually; conflicting values are rejected.
        Missing event time, code, country or location is never synthesized.
      security: []
      parameters:
        - $ref: '#/components/parameters/CluanApiKey'
        - $ref: '#/components/parameters/CluanAuthorization'
        - $ref: '#/components/parameters/CluanTimeStamp'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CluanTrackingRequest'
      responses:
        '200':
          description: Cluan-compatible tracking result for exact customer-owned CLUAN_COMPAT orders.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CluanResponse'
  /compat/t6/api/order/create:
    post:
      summary: Save or update T6-compatible draft orders
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/T6RequestEnvelope' }
      responses:
        '200':
          description: T6 code/msg/data response with per-order results.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/T6Response' }
  /compat/t6/api/order/createForecast:
    post:
      summary: Submit T6-compatible forecast orders through the shared order core
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/T6RequestEnvelope' }
      responses:
        '200':
          description: Per-order forecast result; no placeholder waybill or label is generated.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/T6Response' }
  /compat/t6/api/order/pageOrders:
    post:
      summary: Query T6-compatible orders by documented creation or update date
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/T6RequestEnvelope' }
      responses:
        '200':
          description: Customer-scoped T6 page response.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/T6Response' }
  /compat/t6/api/order/waybillnumber:
    post:
      summary: Query customer, system or waybill numbers through the T6 contract
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/T6RequestEnvelope' }
      responses:
        '200':
          description: Customer-scoped T6 number response.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/T6Response' }
  /compat/t6/api/order/label:
    post:
      summary: Read a verified archived PDF label through the T6 label contract
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/T6RequestEnvelope' }
      responses:
        '200':
          description: Signed short-lived download URL or explicit unavailable reason.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/T6Response' }
  /compat/t6/api/order/express:
    post:
      summary: Read a verified archived PDF waybill through the documented T6 Express path
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/T6RequestEnvelope' }
      responses:
        '200':
          description: Signed short-lived download URL or explicit unavailable reason.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/T6Response' }
  /compat/t6/api/track:
    post:
      summary: Query verified tracking evidence through the T6 contract
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/T6RequestEnvelope' }
      responses:
        '200':
          description: Customer and protocol scoped real tracking events.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/T6Response' }
components:
  parameters:
    AccessKey:
      name: X-Logi-Access-Key
      in: header
      required: true
      schema: { type: string }
    Timestamp:
      name: X-Logi-Timestamp
      in: header
      required: true
      description: Unix epoch milliseconds. Current HMAC verification window is 900 seconds.
      schema: { type: string, pattern: '^[0-9]{13}$' }
    Signature:
      name: X-Logi-Signature
      in: header
      required: true
      schema: { type: string }
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      description: >-
        Client correlation input. The stored key is derived by Logi from authenticated
        company, customer, protocol, external reference and this value.
      schema: { type: string, maxLength: 128 }
    RequestId:
      name: X-Logi-Request-Id
      in: header
      required: false
      schema: { type: string, pattern: '^[A-Za-z0-9._:-]{1,128}$' }
    TraceId:
      name: X-Logi-Trace-Id
      in: header
      required: false
      schema: { type: string, pattern: '^[A-Za-z0-9._:-]{1,128}$' }
    CluanApiKey:
      name: ApiKey
      in: header
      required: true
      schema: { type: string }
    CluanAuthorization:
      name: Authorization
      in: header
      required: true
      description: MD5 hex signature over the documented URI, exact raw UTF-8 body, ApiKey and SecretKey.
      schema: { type: string, pattern: '^[A-Fa-f0-9]{32}$' }
    CluanTimeStamp:
      name: TimeStamp
      in: header
      required: true
      schema: { type: string, pattern: '^[0-9]{13}$' }
  schemas:
    CluanEmptyDataRequest:
      type: object
      required: [timestamp, messageId, data]
      properties:
        timestamp: { type: integer, format: int64 }
        messageId: { type: string }
        data: { type: object, maxProperties: 0 }
    CluanTrackingRequest:
      type: object
      required: [timestamp, messageId, data]
      properties:
        timestamp: { type: integer, format: int64 }
        messageId: { type: string }
        data:
          type: object
          required: [trackingNos]
          properties:
            trackingNos:
              type: array
              minItems: 1
              maxItems: 100
              uniqueItems: true
              items: { type: string }
            trackingType: { type: string, enum: [historical, latest] }
            trackType: { type: string, enum: [historical, latest] }
          additionalProperties: false
    CluanCreateOrderRequest:
      type: object
      required: [timestamp, messageId, data]
      properties:
        timestamp: { type: integer, format: int64 }
        messageId: { type: string, maxLength: 100 }
        data:
          $ref: '#/components/schemas/CluanCreateOrderData'
      additionalProperties: false
    CluanCreateOrderData:
      type: object
      required: [channelCode, referenceNo, customer, clientCode, currency, receiver, parcel]
      properties:
        channelCode: { type: string }
        serviceCode: { type: string }
        referenceNo: { type: string }
        cargoValueType: { type: string }
        platformOrderId: { type: string }
        customer: { type: string }
        clientCode: { type: string }
        sign: { type: string }
        incoterm: { type: string }
        sourceWarehouse: { type: string }
        currency: { type: string, minLength: 3, maxLength: 3 }
        totalDeclareValue: { type: number, minimum: 0 }
        sender: { $ref: '#/components/schemas/CluanAddress' }
        receiver: { $ref: '#/components/schemas/CluanAddress' }
        receiverLocal: { $ref: '#/components/schemas/CluanAddress' }
        pickup: { $ref: '#/components/schemas/CluanAddress' }
        returnInfo: { $ref: '#/components/schemas/CluanAddress' }
        parcel: { $ref: '#/components/schemas/CluanParcel' }
      additionalProperties: false
    CluanAddress:
      type: object
      properties:
        name: { type: string }
        companyName: { type: string }
        phone: { type: string }
        email: { type: string }
        country: { type: string }
        countryCode: { type: string, pattern: '^[A-Za-z]{2}$' }
        province: { type: string }
        city: { type: string }
        district: { type: string }
        street: { type: string }
        postcode: { type: string }
        address: { type: string }
        address1: { type: string }
        address2: { type: string }
        doorplate: { type: string }
        taxId: { type: string }
        iossNo: { type: string }
        vatNo: { type: string }
        eoriNo: { type: string }
      additionalProperties: false
    CluanParcel:
      type: object
      required: [weight, typeNo, productList]
      properties:
        quantity: { type: integer, minimum: 1 }
        typeNo:
          type: integer
          enum: [1, 2, 3, 4]
          description: Public example value 0 remains rejected until the protocol owner confirms its meaning.
        hasBattery: { type: integer, enum: [0, 1] }
        length: { type: number, minimum: 0 }
        width: { type: number, minimum: 0 }
        height: { type: number, minimum: 0 }
        weight: { type: integer, minimum: 1, description: Grams. }
        productList:
          type: array
          minItems: 1
          items: { $ref: '#/components/schemas/CluanProduct' }
      additionalProperties: false
    CluanProduct:
      type: object
      properties:
        skuCode: { type: string }
        descriptionEn: { type: string }
        descriptionLocal: { type: string }
        quantity: { type: integer, minimum: 1 }
        weight: { type: integer, minimum: 1, description: Grams per item. }
        declareValue: { type: number, minimum: 0 }
        currency: { type: string, minLength: 3, maxLength: 3 }
        hsCode: { type: string }
        countryCode: { type: string, pattern: '^[A-Za-z]{2}$' }
        hasBattery: { type: integer, enum: [0, 1] }
        urlLink: { type: string }
      additionalProperties: false
    CluanResponse:
      type: object
      required: [code, message, timestamp, errors]
      properties:
        code: { type: integer }
        message: { type: string }
        timestamp: { type: integer, format: int64 }
        messageId: { type: string, nullable: true }
        data: { type: object, nullable: true, additionalProperties: true }
        errors:
          type: array
          items:
            type: object
            properties:
              code: { type: integer }
              message: { type: string }
    T6RequestEnvelope:
      type: object
      required: [authorization]
      properties:
        authorization:
          type: object
          required: [code, token]
          properties:
            code: { type: string }
            token: { type: string, format: password, writeOnly: true }
          additionalProperties: false
        datas:
          description: Operation-specific T6 request object or array; exact fields follow the documented route.
        page:
          type: object
          additionalProperties: true
      additionalProperties: false
    T6Response:
      type: object
      required: [code, msg]
      properties:
        code: { type: integer }
        msg: { type: string }
        count: { type: integer, format: int64 }
        data:
          nullable: true
    CreateOrderRequest:
      type: object
      required: [referenceNo, salesProductCode, receiver, parcels]
      properties:
        referenceNo:
          type: string
          maxLength: 128
          description: Customer external reference; part of the server-side idempotency scope.
        salesProductCode:
          type: string
          description: A real enabled Logi customer sales product.
        countryCode:
          type: string
          pattern: '^[A-Z]{2}$'
        sender:
          $ref: '#/components/schemas/Address'
        receiver:
          $ref: '#/components/schemas/Address'
        parcels:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/Parcel'
    Address:
      type: object
      properties:
        name: { type: string }
        phone: { type: string }
        countryCode: { type: string, pattern: '^[A-Z]{2}$' }
        state: { type: string }
        city: { type: string }
        postcode: { type: string }
        address1: { type: string }
        address2: { type: string }
        doorplate: { type: string }
    Parcel:
      type: object
      required: [weight]
      properties:
        weight:
          type: integer
          minimum: 1
          description: Grams.
        length: { type: number, description: Centimetres. }
        width: { type: number, description: Centimetres. }
        height: { type: number, description: Centimetres. }
        productList:
          type: array
          items:
            $ref: '#/components/schemas/Item'
    Item:
      type: object
      properties:
        skuCode: { type: string }
        descriptionEn: { type: string }
        quantity: { type: integer, minimum: 1 }
        weight: { type: integer, minimum: 0, description: Grams. }
        declareValue: { type: number, minimum: 0 }
        currency: { type: string, minLength: 3, maxLength: 3 }
        countryCode: { type: string, pattern: '^[A-Z]{2}$' }
    OrderAcceptedEnvelope:
      allOf:
        - $ref: '#/components/schemas/BaseEnvelope'
        - type: object
          properties:
            data:
              type: object
              properties:
                orderNo: { type: string }
                referenceNo: { type: string }
                customerCode: { type: string }
                channelCode: { type: string }
                salesProductCode: { type: string }
                status: { type: string }
                duplicated: { type: boolean }
                acceptedAt: { type: string, format: date-time }
    CapabilityResponse:
      allOf:
        - $ref: '#/components/schemas/BaseEnvelope'
        - type: object
          properties:
            data:
              type: object
              properties:
                apiVersion: { type: string }
                authentication: { type: string }
                replayProtection: { type: string }
                errorModel: { type: string }
                idempotencyScope:
                  type: array
                  items: { type: string }
                auditHeaders:
                  type: array
                  items: { type: string }
                protocols:
                  type: array
                  items:
                    type: object
                    properties:
                      code: { type: string }
                      status: { type: string, enum: [AVAILABLE, DESIGNING, DISABLED] }
                      basePath: { type: string }
                      operations:
                        type: array
                        items: { type: string }
    BaseEnvelope:
      type: object
      required: [success, code, message]
      properties:
        success: { type: boolean }
        code: { type: string }
        message: { type: string }
        requestId: { type: string, nullable: true }
        traceId: { type: string, nullable: true }
        externalReference: { type: string, nullable: true }
    ErrorEnvelope:
      allOf:
        - $ref: '#/components/schemas/BaseEnvelope'
        - type: object
          required: [error]
          properties:
            error:
              $ref: '#/components/schemas/OpenApiError'
    OpenApiError:
      type: object
      required: [code, message, retryable]
      properties:
        code: { type: string }
        message: { type: string }
        field: { type: string, nullable: true }
        retryable: { type: boolean }
        requestId: { type: string, nullable: true }
        traceId: { type: string, nullable: true }
        externalReference: { type: string, nullable: true }
    HualeiAck:
      type: object
      required: [ack, message]
      properties:
        ack: { type: string, enum: ['true', 'false'] }
        message:
          type: string
          description: URL-encoded compatibility message; empty on success.
        customer_id: { type: string }
        customer_userid: { type: string }
        compat_token: { type: string, writeOnly: true }
        token_expires_in: { type: integer, format: int64 }
        order_id: { type: string }
        reference_number: { type: string }
        tracking_number: { type: string }
        order_transfercode: { type: string }
        childList:
          type: array
          items: { type: object, additionalProperties: true }
        requestId: { type: string, nullable: true }
        traceId: { type: string, nullable: true }
