---
title: "Accept an experiment's quote and create an invoice"
method: POST
path: "/api/v1/experiments/{experiment_id}/quote/confirm"
tags: ["experiments"]
---

# Accept an experiment's quote and create an invoice

`POST /api/v1/experiments/{experiment_id}/quote/confirm`

## Request

- Base URL: `https://devs.adaptyvbio.com`
- URL: `https://devs.adaptyvbio.com/api/v1/experiments/{experiment_id}/quote/confirm`
- Auth: HTTP bearer

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).

Convenience endpoint that does the same thing as `POST /quotes/{id}/confirm`
but addressed by experiment ID — the server resolves the quote ID internally.
Like `/quotes/{id}/confirm`, it is **categorically non-settling**: it
finalizes the (open, unpaid) invoice and returns `200` + the invoice + a
HATEOAS `payment` pointer (the Stripe-hosted page for async; `/invoices/{id}/pay`
for a machine rail). It never settles or emits a payment `402`.

## Path parameters

- `experiment_id` string, uuid, 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`: Unknown or inaccessible experiment, malformed request body, or `Content-Type: application/json` declared with no body sent. Every field is optional, so send `{}` if you have nothing to add
- `401`: Invalid or missing authentication token
- `403`: Caller does not have access to this experiment
- `404`: The quote has not been generated yet — poll until 200. Also returned when the experiment was never submitted.
- `409`: Quote cannot be accepted (wrong status or already invoiced)
- `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`: Unprocessable request body (well-formed JSON that fails semantic validation)
- `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)
