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

# Get a quote

> A live JLCPCB price for the upload, delivered with shipping, duty and tax; a custom-quote link (mode review);
or what to answer first (needs_details, needs_part_numbers). The same body within ten minutes is the same
request: it joins the one pricing or answers the quote it priced, and never prices twice.



## OpenAPI

````yaml /api-reference/openapi.json post /v1/quotes
openapi: 3.1.0
info:
  title: ProvenMetal API
  version: 1.0.0
  description: >-
    Everything the ProvenMetal MCP does, over HTTP with an API key: upload a
    design, get a live JLCPCB quote and checkout link, follow it to delivery,
    pay with saved details, and check parts and designs. Formal quotes for any
    fab or assembler are under Orders.
servers:
  - url: https://api.provenmetal.com
security:
  - ApiKey: []
tags:
  - name: Uploads
  - name: Quotes
  - name: Saved details
  - name: Checks
  - name: Buy links
  - name: Orders
  - name: Account
paths:
  /v1/quotes:
    post:
      tags:
        - Quotes
      summary: Get a quote
      description: >-
        A live JLCPCB price for the upload, delivered with shipping, duty and
        tax; a custom-quote link (mode review);

        or what to answer first (needs_details, needs_part_numbers). The same
        body within ten minutes is the same

        request: it joins the one pricing or answers the quote it priced, and
        never prices twice.
      operationId: create_quote_v1_quotes_post
      parameters:
        - name: wait_s
          in: query
          required: false
          schema:
            type: integer
            maximum: 150
            minimum: 0
            description: >-
              Seconds to wait for the quote before answering 202 with a request
              to poll. Bare boards take about 5-25 s; assembled boards up to
              about 2.5 minutes.
            default: 30
            title: Wait S
          description: >-
            Seconds to wait for the quote before answering 202 with a request to
            poll. Bare boards take about 5-25 s; assembled boards up to about
            2.5 minutes.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QuoteRequest'
      responses:
        '201':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/QuoteReply'
        '202':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PendingQuoteReply'
          description: Accepted
        '422':
          description: >-
            A field was refused, or the design needs an answer first
            (needs_details...)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
        4XX:
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
          description: Client Error
        5XX:
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
          description: Server Error
components:
  schemas:
    QuoteRequest:
      properties:
        upload_id:
          type: string
          maxLength: 64
          title: Upload Id
          description: The upload_id from POST /v1/uploads.
        quantity:
          type: integer
          title: Quantity
          description: How many boards, 1 to 100,000.
        ship_to:
          anyOf:
            - $ref: '#/components/schemas/ShipTo'
            - type: 'null'
        assembly:
          type: boolean
          title: Assembly
          description: >-
            true for assembled boards (JLCPCB places the parts), false for bare
            boards. Parts JLCPCB doesn't stock are bought by ProvenMetal from
            authorized distributors and shipped to JLCPCB in one box; the price
            includes that.
          default: false
        layers:
          anyOf:
            - type: integer
            - type: 'null'
          title: Layers
          description: Copper layers, when the files don't state them.
        thickness_mm:
          anyOf:
            - type: number
              maximum: 10
              minimum: 0.1
            - type: 'null'
          title: Thickness Mm
          description: >-
            Board thickness in mm, only when the user or the files state it;
            otherwise it is asked, or 1.6 mm with standard_for_unstated.
        surface_finish:
          anyOf:
            - type: string
              enum:
                - enig
                - hasl_lead_free
                - hasl
            - type: 'null'
          title: Surface Finish
          description: >-
            The finishes JLCPCB's API prices. OSP, ENEPIG and immersion tin or
            silver aren't among them: they need special_requirements=true, a
            custom quote.
        solder_mask:
          anyOf:
            - type: string
              enum:
                - Green
                - Red
                - Blue
                - White
                - Black
                - Yellow
                - Purple
                - Transparent
            - type: 'null'
          title: Solder Mask
          description: >-
            The gloss colours JLCPCB's API prices. A matte mask isn't among
            them: it needs special_requirements=true, a custom quote.
        copper_oz:
          anyOf:
            - type: number
              maximum: 12
              minimum: 0.1
            - type: 'null'
          title: Copper Oz
          description: >-
            Outer copper in oz, only when the user or the files state it;
            otherwise it is asked, or 1 oz with standard_for_unstated.
        inner_copper_oz:
          anyOf:
            - type: number
              maximum: 12
              minimum: 0.1
            - type: 'null'
          title: Inner Copper Oz
          description: >-
            Inner-layer copper of a 4+ layer board, in oz, only when the user or
            the design files state it. JLCPCB's standard is 0.5 oz. KiCad's
            default stackup lists 0.035 mm (1 oz) on every copper layer whether
            or not anyone chose it, so don't pass 1 from that. Left out, it is
            asked, or 0.5 oz with standard_for_unstated.
        material:
          anyOf:
            - type: string
              enum:
                - FR-4
                - FR-4 / TG155
                - FR-4 / TG170
                - Aluminum
                - Copper core
                - Rogers 4350B
                - ZYF300CA-P
                - ZYF300CA-C
                - ZYF265D
                - ZYF255DA
                - Polyimide
            - type: 'null'
          title: Material
          description: >-
            Only when the user or the files state it. Any other laminate is
            special_requirements=true.
        jlc_options:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Jlc Options
          description: >-
            Exact selections from JLCPCB's documented PCB options object (call
            jlcpcb_capabilities): services (serviceConfigCode,
            serviceConfigShow, configOptionShow), gold fingers, castellations,
            electrical test, marking, rails, ENIG gold thickness and flex
            options; the live quote checks availability and fees. Blind slots
            need an order-owned image and take a reviewed quote.
        via_process:
          anyOf:
            - type: string
              enum:
                - tented
                - untented
                - plugged
                - epoxy_filled_capped
                - copper_paste_filled_capped
            - type: 'null'
          title: Via Process
          description: >-
            Filled or plugged vias, priced instantly, when the user or the files
            call for them. Blind, buried or micro vias are
            special_requirements=true.
        impedance_controlled:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Impedance Controlled
          description: >-
            true, with jlc_stackup, for controlled impedance on the JLCPCB
            stackup the design was made for: priced instantly. Impedance on the
            board's own stackup is special_requirements=true.
        jlc_stackup:
          anyOf:
            - type: string
            - type: 'null'
          title: Jlc Stackup
          description: >-
            The JLCPCB stackup the design was made for, for example
            JLC04161H-7628.
        file_stackup:
          anyOf:
            - type: string
              enum:
                - replace
                - keep
            - type: 'null'
          title: File Stackup
          description: >-
            When the files carry their own layer stackup, ask the user: replace
            lets JLCPCB's be used; keep makes it a custom quote.
        separate_boards:
          anyOf:
            - type: string
              enum:
                - one_panel
                - separately
            - type: 'null'
          title: Separate Boards
          description: >-
            When one file holds several boards (two keyboard halves in one
            frame), ask the user: one_panel builds it as drawn, separately as
            separate boards. ProvenMetal's team quotes either.
        special_requirements:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Special Requirements
          description: >-
            true only when the board needs something the other options can't
            express: an OSP, ENEPIG or immersion tin or silver finish or a matte
            mask (none of which JLCPCB's API offers), blind, buried or micro
            vias, rigid-flex, an unmapped laminate, or impedance on the board's
            own stackup; describe it in special_notes. It makes a custom quote
            with no instant price, and its parts aren't checked: tell the user
            before quoting, so they choose. Notes alone don't need it: send them
            in special_notes with false.
        special_notes:
          anyOf:
            - type: string
            - type: 'null'
          title: Special Notes
          description: >-
            The user's words for ProvenMetal's team. With
            special_requirements=true, what is special about the board; with
            false, notes that don't change it, which reach the team with the
            order while the price stays instant.
        standard_for_unstated:
          type: boolean
          title: Standard For Unstated
          description: >-
            true only when the user accepts JLCPCB's standard for whatever
            neither they nor the files state: 1.6 mm, lead-free HASL, 1 oz outer
            and 0.5 oz inner copper, green, FR-4 and no special requirements.
            What the files call for (filled vias, impedance, their own stackup)
            is still asked.
          default: false
        board:
          anyOf:
            - type: string
            - type: 'null'
          title: Board
          description: Which .kicad_pcb to use when the upload holds more than one.
        skip_board_checks:
          type: boolean
          title: Skip Board Checks
          description: >-
            true only if the user wants a KiCad board with shorts or unrouted
            connections built as designed anyway; the quote says so.
          default: false
        project_name:
          anyOf:
            - type: string
              maxLength: 200
            - type: 'null'
          title: Project Name
          description: A name for the board, shown on the order.
        board_context:
          anyOf:
            - type: string
            - type: 'null'
          title: Board Context
          description: >-
            If the user described what the board is for or stated preferences
            (deadline, budget, quantities, priorities) in this conversation or a
            project file, a sentence or two summarising it; leave it out
            otherwise and never include personal details.
        customer_supplied_refs:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Customer Supplied Refs
          description: >-
            References of parts the user says they will send (for example U1,
            L1, Y1), never to get around a review. They stay assembled; the
            customer ships them to ProvenMetal, 1230 Howard Street, San
            Francisco (also in the notes and at checkout).
        do_not_fit_refs:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Do Not Fit Refs
          description: >-
            Whole BOM lines the user says to leave unfitted (for example R21,
            R24); the reply says they were left off. Never delete or change the
            user's files to leave a part off. A line the BOM marks do-not-fit,
            or one with no pick-and-place position (off_board_parts: JLCPCB
            wouldn't assemble it), comes back asking: pass it here only if the
            user says so.
        substitutions:
          anyOf:
            - items:
                $ref: '#/components/schemas/Substitution'
              type: array
            - type: 'null'
          title: Substitutions
          description: >-
            Component changes, only with the customer's explicit approval: one
            entry per reference. To approve a similar_part, its mpn is the
            replacement. At most 300.
        staff_picks_parts:
          type: boolean
          title: Staff Picks Parts
          description: >-
            true only if the user wants ProvenMetal to choose the parts the BOM
            doesn't name exactly (turnkey): each choice comes back in
            picked_parts with other options. Tell the user; to change one, put
            its exact part number in the BOM, upload again and quote. Lines that
            don't say what part they are still come back as needs_part_numbers.
          default: false
        itar:
          type: boolean
          title: Itar
          description: >-
            true only if the user says the design is ITAR-controlled: it can't
            be ordered here.
          default: false
      additionalProperties: false
      type: object
      required:
        - upload_id
        - quantity
      title: QuoteRequest
      description: >-
        Everything the MCP quote tool takes, with the delivery details as one
        ship_to object.
    QuoteReply:
      properties:
        ok:
          type: boolean
          title: Ok
        mode:
          type: string
          enum:
            - instant
            - review
          title: Mode
          description: >-
            instant: a live price the customer pays at checkout_url. review:
            ProvenMetal's team quotes it (custom options, or parts that couldn't
            be priced); the customer requests it at checkout_url.
        quote_id:
          type: string
          title: Quote Id
          description: >-
            64 hex characters: GET /v1/quotes/{quote_id} reports where it
            stands.
        request_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Request Id
          description: The quote request that made it.
        checkout_url:
          type: string
          title: Checkout Url
        quantity:
          type: integer
          title: Quantity
        total:
          anyOf:
            - type: string
            - type: 'null'
          title: Total
          description: Total in USD, delivered, with tax (instant). null for review.
        per_board:
          anyOf:
            - type: string
            - type: 'null'
          title: Per Board
        tax:
          anyOf:
            - type: string
            - type: 'null'
          title: Tax
        currency:
          anyOf:
            - type: string
            - type: 'null'
          title: Currency
          description: 'instant: USD.'
        total_cents:
          anyOf:
            - type: integer
            - type: 'null'
          title: Total Cents
          description: 'instant: the total in cents.'
        per_board_cents:
          anyOf:
            - type: integer
            - type: 'null'
          title: Per Board Cents
        tax_cents:
          anyOf:
            - type: integer
            - type: 'null'
          title: Tax Cents
        lines:
          anyOf:
            - items:
                additionalProperties: true
                type: object
              type: array
            - type: 'null'
          title: Lines
          description: 'instant: what the total is made of, each {label, cents}.'
        board_details:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Board Details
          description: >-
            instant: the board as priced (layers, width_mm, height_mm,
            thickness_mm, copper_oz, inner_copper_oz, surface_finish,
            solder_mask, material).
        assembled:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Assembled
        lead_time:
          anyOf:
            - type: string
            - type: 'null'
          title: Lead Time
          description: Build time.
        delivery:
          anyOf:
            - type: string
            - type: 'null'
          title: Delivery
          description: From payment to the door, build included.
        includes:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Includes
          description: The total's lines, as words.
        board:
          anyOf:
            - type: string
            - type: 'null'
          title: Board
          description: The board in one line.
        board_image_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Board Image Url
          description: A PNG of the board.
        delivery_saved:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Delivery Saved
          description: Checkout opens with the delivery details already saved.
        saved_details:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Saved Details
          description: >-
            The email in ship_to has a saved card and address: the customer can
            pay through /saved/code, /saved/verify and /saved/pay after saying
            yes.
        unpriced_parts:
          anyOf:
            - items:
                additionalProperties: true
                type: object
              type: array
            - type: 'null'
          title: Unpriced Parts
          description: >-
            review: each part that couldn't be priced, with why and what was
            searched, and any similar_part to offer.
        picked_parts:
          anyOf:
            - items:
                additionalProperties: true
                type: object
              type: array
            - type: 'null'
          title: Picked Parts
          description: 'staff_picks_parts: the parts ProvenMetal chose.'
        requested_substitutions:
          anyOf:
            - items:
                additionalProperties: true
                type: object
              type: array
            - type: 'null'
          title: Requested Substitutions
        custom_quote_reasons:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Custom Quote Reasons
          description: 'review: why it needs ProvenMetal''s team.'
        fabrication_quote:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Fabrication Quote
          description: >-
            review of an assembly: an instant price for the bare boards alone,
            with its own checkout_url.
        notes:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Notes
        expires_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Expires At
        next:
          anyOf:
            - type: string
            - type: 'null'
          title: Next
          description: What to do next, in words to relay.
      additionalProperties: true
      type: object
      required:
        - ok
        - mode
        - quote_id
        - checkout_url
        - quantity
      title: QuoteReply
    PendingQuoteReply:
      properties:
        ok:
          type: boolean
          title: Ok
        status:
          type: string
          const: pending
          title: Status
        request_id:
          type: string
          title: Request Id
        poll_url:
          type: string
          title: Poll Url
          description: GET it (optionally with wait_s) for the result.
        retry_after_s:
          type: integer
          title: Retry After S
        elapsed_s:
          type: integer
          title: Elapsed S
        progress:
          type: string
          title: Progress
          description: What the quote is doing now.
      additionalProperties: true
      type: object
      required:
        - ok
        - status
        - request_id
        - poll_url
        - retry_after_s
        - elapsed_s
        - progress
      title: PendingQuoteReply
    ErrorReply:
      properties:
        ok:
          type: boolean
          const: false
          title: Ok
          default: false
        error:
          type: string
          title: Error
          description: >-
            The MCP's error code, for example needs_details, rate_limited or
            no_files.
        message:
          type: string
          title: Message
          description: What went wrong and what to do, in words to relay.
        questions:
          anyOf:
            - items:
                additionalProperties: true
                type: object
              type: array
            - type: 'null'
          title: Questions
          description: >-
            needs_details: each open question with its option, choices and usual
            answer. Answer them and send the same quote again with those fields.
        known:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Known
          description: 'needs_details: what the files already said.'
        parts:
          anyOf:
            - items:
                additionalProperties: true
                type: object
              type: array
            - type: 'null'
          title: Parts
          description: >-
            needs_part_numbers (and needs_details): the BOM lines to name
            exactly.
        off_board_parts:
          anyOf:
            - items:
                additionalProperties: true
                type: object
              type: array
            - type: 'null'
          title: Off Board Parts
          description: BOM lines with no pick-and-place position.
        retry_after_s:
          anyOf:
            - type: integer
            - type: 'null'
          title: Retry After S
          description: 'rate_limited: seconds to wait. Also in the Retry-After header.'
        checkout_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Checkout Url
          description: >-
            card_declined / authentication_required: where the customer pays
            instead.
        fields:
          anyOf:
            - items:
                additionalProperties:
                  type: string
                type: object
              type: array
            - type: 'null'
          title: Fields
          description: 'invalid_request: each field that was refused and why.'
      additionalProperties: true
      type: object
      required:
        - error
        - message
      title: ErrorReply
    ShipTo:
      properties:
        name:
          type: string
          maxLength: 200
          title: Name
          description: The recipient's full name.
          default: ''
        email:
          type: string
          maxLength: 254
          title: Email
          description: >-
            The customer's email: their ProvenMetal account is made with it at
            checkout.
          default: ''
        phone:
          type: string
          maxLength: 40
          title: Phone
          description: A delivery phone number with country code, for the courier.
          default: ''
        company:
          type: string
          maxLength: 200
          title: Company
          default: ''
        line1:
          type: string
          maxLength: 200
          title: Line1
          description: Street address.
          default: ''
        line2:
          type: string
          maxLength: 200
          title: Line2
          default: ''
        city:
          type: string
          maxLength: 100
          title: City
          description: Needed with a country outside the US.
          default: ''
        state:
          type: string
          maxLength: 100
          title: State
          description: >-
            State or province. In Canada and India it (or the postal code) sets
            the tax.
          default: ''
        postal_code:
          type: string
          maxLength: 20
          title: Postal Code
          description: >-
            Only if the customer gave it; never invent one. No price needs it
            outside the US.
          default: ''
        country:
          type: string
          maxLength: 60
          title: Country
          description: Two-letter country code (US if left out).
          default: ''
        tax_id:
          type: string
          maxLength: 40
          title: Tax Id
          description: A tax or VAT ID, only if the customer gave one.
          default: ''
      additionalProperties: false
      type: object
      title: ShipTo
      description: >-
        Who receives the boards and where. Everything is optional; pass only
        what the customer gave, never a guess.

        With name, email, phone, line1, city, postal code and country (and state
        where couriers need one) the checkout

        opens with delivery saved. Without a destination the quote is priced for
        US delivery.
    Substitution:
      properties:
        reference:
          type: string
          maxLength: 4000
          title: Reference
          description: The BOM reference, for example R1.
        original_mpn:
          type: string
          maxLength: 120
          title: Original Mpn
          description: The part the quote showed for that line (or its LCSC code).
        replacement_mpn:
          type: string
          maxLength: 120
          title: Replacement Mpn
          description: >-
            The replacement part number; a similar_part's mpn to approve it, or
            the original_mpn itself to reject a BOM alternate the quote priced
            in.
        replacement_manufacturer:
          anyOf:
            - type: string
              maxLength: 120
            - type: 'null'
          title: Replacement Manufacturer
        reason:
          type: string
          maxLength: 300
          title: Reason
          description: Why, in the customer's words.
      additionalProperties: false
      type: object
      required:
        - reference
        - original_mpn
        - replacement_mpn
        - reason
      title: Substitution
      description: One approved component change, one entry per reference on the BOM line.
  securitySchemes:
    ApiKey:
      type: apiKey
      in: header
      name: X-API-Key
      description: >-
        Your ProvenMetal API key (`pm_live_...`). `Authorization: Bearer <key>`
        also works.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.