> ## Documentation Index
> Fetch the complete documentation index at: https://docs.landedfees.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Bulk landed cost

> Accepts up to 500 single-line rows sharing ship-level fields
(destination, currency, incoterm, transport_mode, freight,
insurance). Freight and insurance are pro-rated across rows by
line value. Row-level validation errors do not fail the batch;
they are returned in the `errors` array alongside successful
rows in `results`.




## OpenAPI

````yaml POST /v1/calc/bulk
openapi: 3.1.0
info:
  title: LandedFees API
  version: 1.0.0
  summary: Landed-cost, HS classification, and origin-comparison API.
  description: |
    LandedFees exposes five stable v1 endpoints for landed-cost calculation,
    HS classification, multi-origin comparison, and rate lookup. All requests
    require a bearer API key (format `sk_live_...`). Every response returns
    JSON. Rate limits are surfaced via `X-RateLimit-*` headers.

    Data provenance: rates resolve against the same live tables the
    LandedFees UI uses (USITC HTS, EU TARIC, HMRC UK Trade Tariff, WCO HS,
    CBP weekly FX per 19 CFR 141.62). No estimates.

    Idempotency: mutation-like endpoints (calc, calc/bulk, classify,
    compare) accept an `Idempotency-Key` header. Repeating the same key
    within 24 hours returns the cached response.
  contact:
    name: LandedFees Support
    url: https://www.landedfees.com/support
    email: support@landedfees.com
  license:
    name: Proprietary
    url: https://www.landedfees.com/terms
servers:
  - url: https://www.landedfees.com
    description: Production (v1)
security:
  - bearerAuth: []
tags:
  - name: Calculate
    description: Landed-cost calculation for single and bulk shipments.
  - name: Classify
    description: HS / HTS code classification from a product description.
  - name: Compare
    description: Side-by-side landed-cost comparison across origins.
  - name: Rates
    description: Duty and tax rate lookup by country and HS code.
paths:
  /v1/calc/bulk:
    post:
      tags:
        - Calculate
      summary: Bulk landed-cost calculation (up to 500 rows).
      description: |
        Accepts up to 500 single-line rows sharing ship-level fields
        (destination, currency, incoterm, transport_mode, freight,
        insurance). Freight and insurance are pro-rated across rows by
        line value. Row-level validation errors do not fail the batch;
        they are returned in the `errors` array alongside successful
        rows in `results`.
      operationId: calcBulk
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CalcBulkRequest'
            examples:
              mixed_sku:
                summary: 3-row mixed-HS shipment CN to US
                value:
                  destination_country: US
                  currency: USD
                  incoterm: FOB
                  transport_mode: ocean
                  freight: 1200
                  insurance: 180
                  rows:
                    - description: Bluetooth earbuds
                      hs_code: '8517.62'
                      quantity: 500
                      unit_value: 12.5
                      origin_country: CN
                    - description: USB-C charging cable
                      hs_code: '8544.42'
                      quantity: 1000
                      unit_value: 1.2
                      origin_country: CN
                    - description: Silicone phone case
                      hs_code: '3926.90'
                      quantity: 800
                      unit_value: 2
                      origin_country: VN
      responses:
        '200':
          description: Bulk calculation completed.
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CalcBulkResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      description: |
        Client-generated unique string (recommended UUID v4). Repeating the
        same key within 24 hours returns the cached response for the original
        request body. Different bodies with the same key return HTTP 409.
      schema:
        type: string
        minLength: 8
        maxLength: 128
        example: e4c1d2a0-8f6b-4c9d-a123-2f8b7c5e9d10
  schemas:
    CalcBulkRequest:
      type: object
      required:
        - destination_country
        - currency
        - incoterm
        - transport_mode
        - rows
      properties:
        destination_country:
          type: string
          minLength: 2
          maxLength: 2
        currency:
          type: string
          minLength: 3
          maxLength: 3
        incoterm:
          $ref: '#/components/schemas/Incoterm'
        transport_mode:
          $ref: '#/components/schemas/TransportMode'
        freight:
          type: number
          minimum: 0
          default: 0
        insurance:
          type: number
          minimum: 0
          default: 0
        eu_member_state:
          type: string
          minLength: 2
          maxLength: 2
        br_state:
          type: string
          minLength: 2
          maxLength: 2
        ca_province:
          type: string
          minLength: 2
          maxLength: 2
        usmca_qualifying:
          type: boolean
        fta_id:
          type: string
        calculation_date:
          type: string
          format: date
        rows:
          type: array
          minItems: 1
          maxItems: 500
          items:
            $ref: '#/components/schemas/CalcBulkRow'
    CalcBulkResponse:
      type: object
      properties:
        id:
          type: string
          format: uuid
          nullable: true
        results:
          type: array
          items:
            $ref: '#/components/schemas/CalcBulkRowResult'
        errors:
          type: array
          items:
            type: object
            properties:
              line_index:
                type: integer
              reason:
                type: string
              field:
                type: string
        aggregate:
          type: object
          properties:
            total_rows:
              type: integer
            ok_rows:
              type: integer
            error_rows:
              type: integer
            total_value:
              type: number
            total_duty:
              type: number
            total_taxes:
              type: number
            total_fees:
              type: number
            total_landed:
              type: number
            currency:
              type: string
    Incoterm:
      type: string
      enum:
        - EXW
        - FCA
        - CPT
        - CIP
        - DAP
        - DPU
        - DDP
        - FAS
        - FOB
        - CFR
        - CIF
    TransportMode:
      type: string
      enum:
        - ocean
        - air
        - truck
        - rail
        - express
    CalcBulkRow:
      type: object
      required:
        - description
        - hs_code
        - quantity
        - unit_value
        - origin_country
      properties:
        description:
          type: string
          minLength: 1
        hs_code:
          type: string
          pattern: ^[0-9.]{4,15}$
          example: '8517.62'
        quantity:
          type: number
          exclusiveMinimum: 0
        unit_value:
          type: number
          minimum: 0
        origin_country:
          type: string
          minLength: 2
          maxLength: 2
        weight_kg:
          type: number
          minimum: 0
          nullable: true
    CalcBulkRowResult:
      type: object
      properties:
        line_index:
          type: integer
        ok:
          type: boolean
        description:
          type: string
        hs_code:
          type: string
        origin:
          type: string
        quantity:
          type: number
        unit_value:
          type: number
        line_value:
          type: number
        duty:
          type: number
        taxes:
          type: number
        fees:
          type: number
        landed_cost:
          type: number
        currency:
          type: string
        de_minimis_applied:
          type: boolean
        warnings:
          type: array
          items:
            type: string
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: string
        code:
          type: string
        message:
          type: string
        detail:
          type: string
        issues:
          type: array
          items:
            type: object
  headers:
    XRateLimitLimit:
      description: Total requests allowed in the current window.
      schema:
        type: integer
        example: 1000
    XRateLimitRemaining:
      description: Requests remaining in the current window.
      schema:
        type: integer
        example: 987
    XRateLimitReset:
      description: Unix epoch seconds when the window resets.
      schema:
        type: integer
        example: 1755273600
  responses:
    BadRequest:
      description: Request body failed validation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: invalid body
            issues:
              - path:
                  - destination_country
                message: String must contain exactly 2 character(s)
    Unauthorized:
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: unauthorized
    PaymentRequired:
      description: >-
        Quota exhausted for the current plan. Upgrade or wait for the monthly
        reset.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: quota_exceeded
            code: QUOTA_EXCEEDED
            message: >-
              Monthly quota exhausted. Upgrade at
              https://www.landedfees.com/pricing.
    TooManyRequests:
      description: Rate limit exceeded. Retry after the reset window.
      headers:
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: rate_limited
            code: RATE_LIMITED
            message: Too many requests. Retry after 60 seconds.
    InternalError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: internal
            detail: engine error
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: sk_live
      description: |
        API key issued from the LandedFees dashboard under Settings > API keys.
        Format: `sk_live_...` (production) or `sk_test_...` (sandbox). Pass in
        the `Authorization: Bearer <key>` header.

````