# Quotes

> Create, finalize, accept, and cancel quotes that convert into subscriptions.

A quote presents a pricing proposal to a prospective customer before they commit to a subscription.
Once accepted, VINR automatically converts the quote into a live subscription.

> **Illustrative content.** Hand-authored to demonstrate the Standard/Advanced pattern; the production
> page will be generated from the VINR OpenAPI spec (roadmap item #1). Field names are representative.

## The quote object

- **id** `string` — Unique identifier for the quote, e.g. `qt_5Bw2xNjR`.
- **customer** `string` (expandable) — The ID of the customer this quote is for, e.g. `cust_8aZ2`. Expand to retrieve the full
  customer object.
- **status** `enum` — Quote lifecycle state: `draft`, `open`, `accepted`, or `canceled`.
- **amount\_total** `integer` — Total amount across all line items, in the smallest currency unit.
- **currency** `string` — Three-letter ISO currency code, e.g. `EUR`.
- **expires\_at** `integer` — Unix timestamp after which the quote can no longer be accepted.
- **line\_items** `array` — The list of products and prices included in the quote. Each item has `price`, `quantity`, and
  `amount_subtotal`.
- **created** `integer` — Unix timestamp of when the quote was created, e.g. `1716300000`.

## Create a quote

Create a quote in `draft` status. Add `line_items` referencing existing prices.

`POST /v1/quotes`

```bash
curl -X POST https://api.vinr.com/v1/quotes \
-H "X-Api-Key: $VINR_SECRET_KEY" \
-d customer=cust_8aZ2 \
-d "line_items[0][price]=price_9Rz1wBqT" \
-d "line_items[0][quantity]=1"
```

```js
import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const quote = await vinr.quotes.create({
customer: 'cust_8aZ2',
line_items: [{ price: 'price_9Rz1wBqT', quantity: 1 }],
});
```

```python
import vinr

quote = vinr.Quote.create(
  customer="cust_8aZ2",
  line_items=[{"price": "price_9Rz1wBqT", "quantity": 1}],
)
```

```ruby
quote = Vinr::Quote.create(
customer: 'cust_8aZ2',
line_items: [{ price: 'price_9Rz1wBqT', quantity: 1 }],
)
```

```json
{
"id": "qt_5Bw2xNjR",
"customer": "cust_8aZ2",
"status": "draft",
"amount_total": 2900,
"currency": "EUR",
"expires_at": null,
"line_items": [
  {
    "price": "price_9Rz1wBqT",
    "quantity": 1,
    "amount_subtotal": 2900
  }
],
"created": 1716300000
}
```

## Retrieve a quote

`GET /v1/quotes/{id}`

```bash
curl https://api.vinr.com/v1/quotes/qt_5Bw2xNjR \
-H "X-Api-Key: $VINR_SECRET_KEY"
```

```js
import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const quote = await vinr.quotes.retrieve('qt_5Bw2xNjR');
```

```python
import vinr

quote = vinr.Quote.retrieve("qt_5Bw2xNjR")
```

```ruby
quote = Vinr::Quote.retrieve('qt_5Bw2xNjR')
```

```json
{
"id": "qt_5Bw2xNjR",
"customer": "cust_8aZ2",
"status": "open",
"amount_total": 2900,
"currency": "EUR",
"expires_at": 1718892000,
"line_items": [
  {
    "price": "price_9Rz1wBqT",
    "quantity": 1,
    "amount_subtotal": 2900
  }
],
"created": 1716300000
}
```

## Update a quote

Update a `draft` or `open` quote. Only `description` and `expires_at` can be changed.

`POST /v1/quotes/{id}`

```bash
curl -X POST https://api.vinr.com/v1/quotes/qt_5Bw2xNjR \
-H "X-Api-Key: $VINR_SECRET_KEY" \
-d description="Special pricing for Q3" \
-d expires_at=1718892000
```

```js
import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const quote = await vinr.quotes.update('qt_5Bw2xNjR', {
description: 'Special pricing for Q3',
expires_at: 1718892000,
});
```

```python
import vinr

quote = vinr.Quote.modify(
  "qt_5Bw2xNjR",
  description="Special pricing for Q3",
  expires_at=1718892000,
)
```

```ruby
quote = Vinr::Quote.update(
'qt_5Bw2xNjR',
description: 'Special pricing for Q3',
expires_at: 1718892000,
)
```

```json
{
"id": "qt_5Bw2xNjR",
"customer": "cust_8aZ2",
"status": "draft",
"amount_total": 2900,
"currency": "EUR",
"expires_at": 1718892000,
"line_items": [
  {
    "price": "price_9Rz1wBqT",
    "quantity": 1,
    "amount_subtotal": 2900
  }
],
"created": 1716300000
}
```

## Finalize a quote

Finalizing moves the quote from `draft` to `open` and makes it shareable with the customer.

`POST /v1/quotes/{id}/finalize`

```bash
curl -X POST https://api.vinr.com/v1/quotes/qt_5Bw2xNjR/finalize \
-H "X-Api-Key: $VINR_SECRET_KEY"
```

```js
import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const quote = await vinr.quotes.finalize('qt_5Bw2xNjR');
```

```python
import vinr

quote = vinr.Quote.finalize("qt_5Bw2xNjR")
```

```ruby
quote = Vinr::Quote.finalize('qt_5Bw2xNjR')
```

```json
{
"id": "qt_5Bw2xNjR",
"status": "open",
"amount_total": 2900,
"currency": "EUR",
"expires_at": 1718892000,
"created": 1716300000
}
```

## Accept a quote

Accepting an `open` quote converts it into a live [subscription](/docs/api-reference/subscriptions)
and moves the quote to `accepted`.

`POST /v1/quotes/{id}/accept`

```bash
curl -X POST https://api.vinr.com/v1/quotes/qt_5Bw2xNjR/accept \
-H "X-Api-Key: $VINR_SECRET_KEY"
```

```js
import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const quote = await vinr.quotes.accept('qt_5Bw2xNjR');
```

```python
import vinr

quote = vinr.Quote.accept("qt_5Bw2xNjR")
```

```ruby
quote = Vinr::Quote.accept('qt_5Bw2xNjR')
```

```json
{
"id": "qt_5Bw2xNjR",
"status": "accepted",
"amount_total": 2900,
"currency": "EUR",
"subscription": "sub_2Lq7dKrM",
"created": 1716300000
}
```

## Cancel a quote

Canceling a `draft` or `open` quote prevents it from being accepted.

`POST /v1/quotes/{id}/cancel`

```bash
curl -X POST https://api.vinr.com/v1/quotes/qt_5Bw2xNjR/cancel \
-H "X-Api-Key: $VINR_SECRET_KEY"
```

```js
import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const quote = await vinr.quotes.cancel('qt_5Bw2xNjR');
```

```python
import vinr

quote = vinr.Quote.cancel("qt_5Bw2xNjR")
```

```ruby
quote = Vinr::Quote.cancel('qt_5Bw2xNjR')
```

```json
{
"id": "qt_5Bw2xNjR",
"status": "canceled",
"amount_total": 2900,
"currency": "EUR",
"created": 1716300000
}
```

## List quotes

`GET /v1/quotes`

```bash
curl "https://api.vinr.com/v1/quotes?customer=cust_8aZ2&status=open&limit=10" \
-H "X-Api-Key: $VINR_SECRET_KEY"
```

```js
import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const quotes = await vinr.quotes.list({
customer: 'cust_8aZ2',
status: 'open',
limit: 10,
});
```

```python
import vinr

quotes = vinr.Quote.list(
  customer="cust_8aZ2",
  status="open",
  limit=10,
)
```

```ruby
quotes = Vinr::Quote.list(
customer: 'cust_8aZ2',
status: 'open',
limit: 10,
)
```

```json
{
"object": "list",
"data": [
  {
    "id": "qt_5Bw2xNjR",
    "customer": "cust_8aZ2",
    "status": "open",
    "amount_total": 2900,
    "currency": "EUR",
    "expires_at": 1718892000,
    "created": 1716300000
  }
],
"has_more": false
}
```

## Related events

`quote.created`, `quote.finalized`, `quote.accepted`, and `quote.canceled`. See [Events](/docs/api-reference/events).
