---
title: "Calculate Bend Pricing Experiment Endpoint"
method: POST
path: "/quotes/calculate/bend-pricing-experiment"
tags: ["quotes"]
---

# Calculate Bend Pricing Experiment Endpoint

`POST /quotes/calculate/bend-pricing-experiment`

Compare current quote pricing against an experimental bend pricing model.

## Request body

- CalculateAssemblyQuoteRequest — Request model for calculating final pricing on an assembly quote. Takes an existing AssemblyQuoteResponse and applies quantities to calculate final pricing including discounts and totals.
  - `assembly_quote` AssemblyQuoteResponse, required — Response model for an assembly quote. Returns the individual quotes for each design and an aggregate total price for the entire assembly. Secondary-operation details for each design are preserved in their respective QuoteResponse objects so that callers can surface them if desired.
    - `assembly_id` string, nullable
    - `quotes` QuoteResponse[], required
      - `unit_price` integer, required
      - `secondary_operations` SecondaryOperation[], required
        - `name` string, required
        - `pricing` union, required
          - BendPricing
            - `price_per_bend` UnitPricing[], required
              - …
            - `num_bends` integer, required
          - TapPricing
            - `price_per_tap` UnitPricing[], required
              - …
            - `num_taps` integer, required
            - `base_price` integer, required
          - StudPricing
            - `price_per_stud` UnitPricing[], required
              - …
            - `num_studs` integer, required
            - `base_price` integer, required
          - NutPricing
            - `price_per_nut` UnitPricing[], required
              - …
            - `num_nuts` integer, required
            - `base_price` integer, required
          - CountersinkPricing
            - `price_per_countersink` UnitPricing[], required
              - …
            - `num_countersinks` integer, required
            - `base_price` integer, required
          - PowderCoatPricing
            - `color` string, required
            - `base_price` integer, required
            - `price_per_cm2` number, required
            - `surface_area_cm2` number, required
            - `price_tiers` UnitPricing[], required
              - …
          - MechanicalFinishPricing
            - `finish_type` string, required
            - `base_price` integer, required
            - `price_per_cm2` number, required
            - `surface_area_cm2` number, required
            - `price_tiers` UnitPricing[], required
              - …
      - `discounts` Discount[], required
        - `quantity` integer, required
        - `discount_percent` number, required
      - `material` MaterialTable
        - `id` string, required
        - `material` 'Steel' | 'Aluminum' | 'Stainless Steel', required
        - `type` string, required
        - `thickness_in` number, nullable
        - `thickness_mm` number, nullable
        - `weight_cm2` number, nullable
        - `display_thickness` string, nullable
        - `bendable` boolean, nullable
        - `ultimate_tensile_strength_psi` integer, nullable
        - `yield_tensile_strength_psi` integer, nullable
      - `tube_profile` TubeProfileTable
        - `id` string, required
        - `material` 'Steel' | 'Aluminum' | 'Stainless Steel', required
        - `type` string, required
        - `shape` string, required
        - `display_name` string, required
        - `outer_width_mm` number, nullable
        - `outer_height_mm` number, nullable
        - `outer_diameter_mm` number, nullable
        - `inner_diameter_mm` number, nullable
        - `wall_thickness_mm` number, nullable
        - `outer_corner_radius_mm` number, nullable
        - `inner_corner_radius_mm` number, nullable
        - `weight_kg_per_m` number, nullable
        - `default_stock_length_mm` number, nullable
        - `active` boolean
      - `tube_pricing` TubePricingBreakdown — Cost/margin snapshot behind a tube quote, for audit and calibration. Persisting this with the quote is what lets predicted material/machine numbers be compared against factory actuals later.
        - `pricing_model` string, required
        - `material_cents` number, required
        - `machine_cents` number, required
        - `handling_cents` number, required
        - `unit_cost_cents` number, required
        - `machine_time_s` number, required
        - `length_mm` number, required
        - `stock_cost_per_mm_cents` number, required
        - `utilization_factor` number, required
        - `margin_at_unit_price` number, required
        - `pooled_material_cents` number, required
      - `manufacturability` QuoteManufacturability — Complete manufacturability result for one quoted configuration.
        - `is_manufacturable` boolean, required
        - `issues` QuoteManufacturabilityIssue[]
          - `code` string, required
          - `message` string, required
          - `source` 'planner' | 'reason_api', required
          - `blocking` boolean
          - `design_id` string, required
          - `bend_id` integer, nullable
          - `hole_id` integer, nullable
          - `material` string, nullable
          - `material_type` string, nullable
          - `actual_length_mm` number, nullable
          - `min_length_mm` number, nullable
          - `max_length_mm` number, nullable
          - `actual_angle_degrees` number, nullable
          - `max_angle_degrees` number, nullable
          - `required_tonnage` number, nullable
          - `max_tonnage` number, nullable
          - `thickness_mm` number, nullable
          - `designed_thickness_mm` number, nullable
          - `designed_bend_radius_mm` number, nullable
          - `tooling_bend_radius_mm` number, nullable
          - `die_id` string, nullable
          - `die_name` string, nullable
          - `die_v_width_mm` number, nullable
          - `die_selection` 'preferred_calibration' | 'best_guess_8x_thickness', nullable
          - `ultimate_tensile_strength_psi` number, nullable
          - `distance_mm` number, nullable
          - `min_distance_mm` number, nullable
      - `design` QuoteDesign, required — Customer-safe design metadata embedded in quote responses. Pricing needs the analyzed geometry, but callers do not need database ownership fields, anonymous bearer tokens, or internal storage paths. A serialized quote can therefore be sent back to `/quotes/calculate` without carrying any of those secrets.
        - `id` string, required
        - `file_name` string, required
        - `part_type` 'sheet' | 'tube'
        - `part_name` string, nullable
        - `file_size` integer, required
        - `bends` Bend[], required
          - `id` integer, required
          - `angle` number, required
          - `radius` number, required
          - `location` BentLocation, required
            - `x` number, required
            - `y` number, required
            - `z` number, required
          - `direction` BentLocation, required
            - `x` number, required
            - `y` number, required
            - `z` number, required
          - `length` number, required
          - `line_start` BentLocation
            - `x` number, required
            - `y` number, required
            - `z` number, required
          - `line_end` BentLocation
            - `x` number, required
            - `y` number, required
            - `z` number, required
          - `distortion_zone_sides` BendDistortionZoneSide[]
            - `source_hole_id` integer, nullable
            - `edge_start` BentLocation, required
              - …
            - `edge_end` BentLocation, required
              - …
            - `outward_direction` BentLocation, required
              - …
        - `thickness` number, required
        - `surface_area_cm2` number, required
        - `bounding_dimensions` number[], required
        - `flat_bounding_dimensions_mm` number[], required
        - `manufacturability` 'manufacturable' | 'not_within_shippable_dimensions' | 'not_within_manufacturable_dimensions', required
        - `manufacturability_details` string[], nullable, required
        - `cut_length_mm` number, nullable
        - `hole_count` integer, nullable
        - `flat_pattern_number_of_interior_boundaries` integer, required
        - `original_holes` Hole[], nullable
          - `id` integer, required
          - `area_mm2` number, required
          - `center` Point3D, required
            - `x` number, required
            - `y` number, required
            - `z` number, required
          - `diameter_mm` number, required
          - `perimeter_mm` number, required
          - `hole_center_dist_to_nearest_edge` number, required
          - `normal` Normal, required
            - `x` number, required
            - `y` number, required
            - `z` number, required
          - `nearest_bend` NearestBend
            - `bend_id` integer, nullable
            - `distance_to_flange` number, nullable
            - `is_inner_cylindrical_face` boolean, nullable
            - `outside_bend_path` boolean, nullable
            - `line_start` Point3D
              - …
            - `line_end` Point3D
              - …
            - `distortion_zone_side` BendDistortionZoneSide — Planner geometry for one sheet side adjacent to a bend line.
              - …
          - `nearby_bends` NearestBend[]
            - `bend_id` integer, nullable
            - `distance_to_flange` number, nullable
            - `is_inner_cylindrical_face` boolean, nullable
            - `outside_bend_path` boolean, nullable
            - `line_start` Point3D
              - …
            - `line_end` Point3D
              - …
            - `distortion_zone_side` BendDistortionZoneSide — Planner geometry for one sheet side adjacent to a bend line.
              - …
          - `outline` Point3D[], nullable
            - `x` number, required
            - `y` number, required
            - `z` number, required
        - `flange_lengths` union[], required
          - union
            - FlangeLength
              - …
            - number
        - `backgauge_flanges` object[], required
        - `u_channels` object[]
        - `transformed_holes` Hole[], nullable
          - `id` integer, required
          - `area_mm2` number, required
          - `center` Point3D, required
            - `x` number, required
            - `y` number, required
            - `z` number, required
          - `diameter_mm` number, required
          - `perimeter_mm` number, required
          - `hole_center_dist_to_nearest_edge` number, required
          - `normal` Normal, required
            - `x` number, required
            - `y` number, required
            - `z` number, required
          - `nearest_bend` NearestBend
            - `bend_id` integer, nullable
            - `distance_to_flange` number, nullable
            - `is_inner_cylindrical_face` boolean, nullable
            - `outside_bend_path` boolean, nullable
            - `line_start` Point3D
              - …
            - `line_end` Point3D
              - …
            - `distortion_zone_side` BendDistortionZoneSide — Planner geometry for one sheet side adjacent to a bend line.
              - …
          - `nearby_bends` NearestBend[]
            - `bend_id` integer, nullable
            - `distance_to_flange` number, nullable
            - `is_inner_cylindrical_face` boolean, nullable
            - `outside_bend_path` boolean, nullable
            - `line_start` Point3D
              - …
            - `line_end` Point3D
              - …
            - `distortion_zone_side` BendDistortionZoneSide — Planner geometry for one sheet side adjacent to a bend line.
              - …
          - `outline` Point3D[], nullable
            - `x` number, required
            - `y` number, required
            - `z` number, required
        - `countersinks` AnalyzedCountersink[], nullable
          - `id` integer, required
          - `center` Point3D, required
            - `x` number, required
            - `y` number, required
            - `z` number, required
          - `normal` Normal, required
            - `x` number, required
            - `y` number, required
            - `z` number, required
          - `inverted` boolean, required
          - `counters_sink_inner_radius` number, required
          - `counters_sink_outer_radius` number, required
          - `counter_sink_angle` number, required
        - `design_tree` object, nullable
        - `detected_tube_profile_key` string, nullable
        - `tube_profile_id` string, nullable
        - `tube_length_mm` number, nullable
        - `tube_features` object[]
        - `tube_holes` object[]
        - `tube_metadata` object
        - `public` boolean, required
        - `issues` Issue[], required
          - `bend_id` integer, required
          - `issue` string, required
        - `assembly_id` string, nullable
    - `weld_cost_cents` integer, nullable
    - `welds` Weld[], nullable
      - `type` string, required
      - `length` number, required
      - `part_ids` string[], nullable
      - `finish` 'none' | 'rough' | 'fine'
      - `joint_access` 'open' | 'tight' | 'blind'
    - `weld_discounts` Discount[], nullable
      - `quantity` integer, required
      - `discount_percent` number, required
    - `weld_pricing` WeldPricingBreakdown — Full parametric weld pricing for an assembly quote. `weld_unit_cost_cents` (seams + finishing for ONE assembly) scales with quantity via the qty run-rate discounts; the setup and fixturing fees are charged once per order and never discounted.
      - `welds` WeldLineItem[], required
        - `length_cm` number, required
        - `process` string, required
        - `material_family` string, required
        - `rate_per_inch_cents` integer, required
        - `thickness_multiplier` number, required
        - `access_multiplier` number, required
        - `weld_cost_cents` integer, required
        - `finish` string, required
        - `finish_cost_cents` integer, required
      - `weld_unit_cost_cents` integer, required
      - `setup_fee_cents` integer, required
      - `fixturing_piece_fee_cents` integer, required
      - `fixturing_size_fee_cents` integer, required
      - `one_time_fees_cents` integer, required
      - `part_sqft` number, required
      - `piece_count` integer, required
  - `assembly_quantity` integer, required
  - `design_quantities` DesignQuantity[], required
    - `design_id` string, required
    - `quantity` integer, required
  - `requested_quantity_range` RequestedQuantityRange — Inclusive range of assembly quantities to precompute.
    - `min_quantity` integer, required
    - `max_quantity` integer, required
  - `requested_quantities` integer[], nullable

## Response `200`

Successful Response

- BendPricingExperimentResponse
  - `parameters` ExperimentalBendPricingParameters, required — Inputs used by the proposed bend pricing experiment.
    - `model` string, required
    - `brake_setup_cost_recovery_cents_per_hour` integer, required
    - `brake_run_sell_rate_cents_per_hour` integer, required
    - `single_bend_program_and_tooling_setup_minutes` number, required
    - `multi_bend_program_and_tooling_setup_minutes` number, required
    - `extra_setup_minutes_per_bend_after_first` number, required
    - `first_part_seconds_per_bend` number, required
    - `repeat_seconds_per_bend_parts_2_to_10` number, required
    - `repeat_seconds_per_bend_parts_11_to_50` number, required
    - `repeat_seconds_per_bend_parts_51_plus` number, required
    - `one_bend_risk_percent` number, required
    - `two_to_three_bend_risk_percent` number, required
    - `four_to_seven_bend_risk_percent` number, required
    - `eight_plus_bend_risk_percent` number, required
    - `minimum_unit_bend_price_cents` integer, required
  - `current` CalculatedAssemblyQuote, required — Response model for calculated assembly pricing (matches frontend interface).
    - `assembly` AssemblyTotals, required — Aggregate totals for the entire assembly.
      - `partCostTotal` integer, required
      - `weldCostTotal` integer, required
      - `totalAmountAfterDiscount` integer, required
      - `effectiveUnitCost` integer, required
    - `designs` CalculatedQuote[], required
      - `originalUnitAmount` integer, required
      - `discountAmount` integer, required
      - `discountPercent` number, required
      - `priceAfterDiscount` integer, required
      - `totalAmountBeforeSecondaryOperations` integer, required
      - `totalBendCost` integer, required
      - `totalTapCost` integer, required
      - `totalStudCost` integer, required
      - `totalNutCost` integer, required
      - `totalCountersinkCost` integer, required
      - `totalPowderCoatCost` integer, required
      - `totalFinishCost` integer
      - `totalAmount` integer, required
      - `effectiveUnitCost` integer, required
      - `designId` string, required
      - `pricingVersion` string, nullable
      - `pricingMetadata` PricingMetadata — Version metadata for the pricing logic that generated a quote.
        - `pricingVersion` string, required
        - `calculator` string, required
        - `components` object, required
        - `configHash` string, required
        - `snapshot` object
    - `pricingVersion` string, nullable
    - `pricingMetadata` PricingMetadata — Version metadata for the pricing logic that generated a quote.
      - `pricingVersion` string, required
      - `calculator` string, required
      - `components` object, required
      - `configHash` string, required
      - `snapshot` object
  - `proposed` CalculatedAssemblyQuote, required — Response model for calculated assembly pricing (matches frontend interface).
    - `assembly` AssemblyTotals, required — Aggregate totals for the entire assembly.
      - `partCostTotal` integer, required
      - `weldCostTotal` integer, required
      - `totalAmountAfterDiscount` integer, required
      - `effectiveUnitCost` integer, required
    - `designs` CalculatedQuote[], required
      - `originalUnitAmount` integer, required
      - `discountAmount` integer, required
      - `discountPercent` number, required
      - `priceAfterDiscount` integer, required
      - `totalAmountBeforeSecondaryOperations` integer, required
      - `totalBendCost` integer, required
      - `totalTapCost` integer, required
      - `totalStudCost` integer, required
      - `totalNutCost` integer, required
      - `totalCountersinkCost` integer, required
      - `totalPowderCoatCost` integer, required
      - `totalFinishCost` integer
      - `totalAmount` integer, required
      - `effectiveUnitCost` integer, required
      - `designId` string, required
      - `pricingVersion` string, nullable
      - `pricingMetadata` PricingMetadata — Version metadata for the pricing logic that generated a quote.
        - `pricingVersion` string, required
        - `calculator` string, required
        - `components` object, required
        - `configHash` string, required
        - `snapshot` object
    - `pricingVersion` string, nullable
    - `pricingMetadata` PricingMetadata — Version metadata for the pricing logic that generated a quote.
      - `pricingVersion` string, required
      - `calculator` string, required
      - `components` object, required
      - `configHash` string, required
      - `snapshot` object
  - `comparison` BendPricingAssemblyComparison, required
    - `assemblyQuantity` integer, required
    - `currentTotalAmount` integer, required
    - `proposedTotalAmount` integer, required
    - `totalDeltaCents` integer, required
    - `totalDeltaPercent` number, required
    - `currentEffectiveUnitCost` integer, required
    - `proposedEffectiveUnitCost` integer, required
    - `effectiveUnitDeltaCents` integer, required
    - `currentTotalBendCost` integer, required
    - `proposedTotalBendCost` integer, required
    - `bendDeltaCents` integer, required
    - `designs` BendPricingDesignComparison[], required
      - `designId` string, required
      - `quantity` integer, required
      - `numBends` integer, required
      - `currentTotalBendCost` integer, required
      - `proposedTotalBendCost` integer, required
      - `bendDeltaCents` integer, required
      - `currentTotalAmount` integer, required
      - `proposedTotalAmount` integer, required
      - `totalDeltaCents` integer, required
      - `currentEffectiveUnitCost` integer, required
      - `proposedEffectiveUnitCost` integer, required
      - `effectiveUnitDeltaCents` integer, required
      - `proposedBendBreakdown` ExperimentalBendPricingBreakdown — Per-design bend cost breakdown for the proposed pricing experiment.
        - `designId` string, required
        - `quantity` integer, required
        - `numBends` integer, required
        - `setupMinutes` number, required
        - `runSecondsPerBendPerPart` number, required
        - `totalRunSeconds` number, required
        - `riskPercent` number, required
        - `setupCostCents` integer, required
        - `runCostCents` integer, required
        - `riskCostCents` integer, required
        - `totalBendCostCents` integer, required
        - `unitBendCostCents` integer, required
  - `quantityComparisons` object, nullable

## Other responses

- `404` — Not found
- `422` — Validation Error

---

[API](https://skmtc.dev/rmfg/apis/fastapi.md) · [All operations](https://skmtc.dev/rmfg/apis/fastapi/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/rmfg/fastapi/revisions/17a4ad42a016/schema)
