---
title: "Accept quote"
method: POST
path: "/api/v1/quotes/{quote_id}/confirm"
tags: ["quotes"]
---

# Accept quote

`POST /api/v1/quotes/{quote_id}/confirm`

## Request

- Base URL: `https://devs.adaptyvbio.com`
- URL: `https://devs.adaptyvbio.com/api/v1/quotes/{quote_id}/confirm`
- Auth: HTTP bearer

Finalizes and accepts a Stripe quote, creating the (open, unpaid)
invoice and advancing the linked experiment to `WaitingForMaterials`.
Optionally attach a purchase order number for your records.

A JSON body is required. Every field of `ConfirmQuoteRequest` is
optional, so a caller with no purchase-order number and no notes sends
`{}` — the refusal says so if they forget (BUG-0059).

This endpoint is **categorically non-settling**: it never settles a
payment and never emits a payment `402`. The `200` response carries the
finalized invoice plus a HATEOAS `payment` pointer telling you where and
how to pay — the Stripe-hosted page for an async-invoice quote, or
`POST /invoices/{invoice_id}/pay` for a machine rail (x402-exact /
mpp-spt), where the `402` challenge is answered.

The quote must be in a confirmable state ("Waiting for confirmation" or
"Quote sent") and must not already have an invoice. Expired or otherwise
non-confirmable quotes return 409.

## Path parameters

- `quote_id` string, required

## Request body

- ConfirmQuoteRequest: Request payload for accepting a quote Used when a customer decides to accept a quoted price.
  - `notes` string, nullable: Reserved for future use. Currently accepted but not acted upon.
  - `purchase_order_number` string, nullable: Purchase order number from your organization (optional)

## Response `200`

Quote accepted; the (open, unpaid) invoice is finalized and the `payment` block points at where/how to pay

- ConfirmQuoteResponse: Response after accepting a quote Confirms the quote acceptance and provides invoice information if applicable.
  - `hosted_invoice_url` string, nullable: Stripe-hosted URL where the customer can view and pay the generated invoice
  - `id` string, required: Quote ID that was accepted
  - `invoice_id` string, nullable: ID of the invoice generated from this quote (if applicable)
  - `payment` PaymentLink: Hypermedia pointer to where and how to pay the invoice a confirm finalized. `POST /quotes/{id}/confirm` is categorically non-settling: it finalizes the (open, unpaid) invoice and hands back this block instead of settling or emitting a payment `402`. Exactly one shape is populated per response, discriminated by `kind`: - `hosted_invoice`: async-invoice quotes. Pay via `hosted_invoice_url` (the Stripe-hosted page); `pay_url`/`methods` are absent. - `machine`: a machine rail (x402-exact / mpp-spt). POST to `pay_url` (`/api/v1/invoices/{invoice_id}/pay`) to answer the `402` challenge and settle; `methods` lists the accepted rails by their `X-Adaptyv-Payment-Method` spellings.
    - `hosted_invoice_url` string, nullable: Stripe-hosted invoice page (async-invoice only); pay here.
    - `kind` 'hosted_invoice' | 'machine', required: Which payment surface a confirm [`PaymentLink`] points at.
    - `methods` string[]: Machine-payment rails accepted at `pay_url` (machine rail only), by their `X-Adaptyv-Payment-Method` header spellings.
    - `pay_url` string, nullable: Machine-payment endpoint to POST to (machine rail only): answers the `402` challenge and settles the invoice.
  - `status` 'draft' | 'open' | 'accepted' | 'canceled' | 'stale', required: Quote status from Stripe's API.

## Other responses

- `400`: Malformed request body, or `Content-Type: application/json` was declared and no body sent. Every field is optional, so send `{}` if you have nothing to add
- `403`: Insufficient permissions to accept this quote
- `404`: Quote not found
- `409`: Quote cannot be accepted (wrong status, already accepted, or a payment method whose Stripe tier does not match the one pinned at creation)
- `415`: No body was sent, or a body was sent under a content type other than `application/json`. A JSON body is required; send `{}` if you have nothing to add
- `422`: Well-formed JSON that does not fit `ConfirmQuoteRequest`
- `429`: Stripe rate-limited the quote call; retry after `Retry-After` seconds
- `500`: Internal server error
- `502`: Stripe refused or failed a call on the quote. The cause is on Adaptyv's side and Adaptyv has been alerted; the message says whether retrying can help

---

[API](https://skmtc.dev/adaptyvbio/apis/adaptyv-foundry-api.md) - [All operations](https://skmtc.dev/adaptyvbio/apis/adaptyv-foundry-api/llms.txt) - [OpenAPI document](https://skmtc.dev/adaptyvbio/apis/adaptyv-foundry-api/revisions/5a2228f4bd59?raw)
