Skip to main content

Create Quote

Create a new quote. The payload takes the same line items as Create Booking โ€” products, bundles, experiences, store products, dates, discount โ€” plus three quote-specific fields. Prices are calculated by the same engine as bookings, so the quoted total always matches what the equivalent booking would cost.

POST /v1/quotes

Authenticationโ€‹

Requires a valid API key with quotes:write scope.

Request Bodyโ€‹

All the line-item fields from Create Booking apply โ€” products, bundles, experiences, store_products, start_date, end_date, discount, pickup_location_id, return_location_id, and their nested shapes are identical. On top of those:

FieldTypeRequiredDescription
customer_idintegerYesID of an existing customer
booking_typestringNorental, experience, store, service, or mixed
quote_reservesbooleanNoHold the quoted dates while the customer decides (default: false). Held dates are released automatically if the quote is declined or expires.
quote_valid_untildateNoExpiry date (YYYY-MM-DD, today or later). Omit for a quote that never expires.
quote_agreement_form_idsinteger[]NoIDs of published waiver/form documents the customer signs on the quote page โ€” a quote can carry several agreements. Takes precedence over quote_agreement_form_id
quote_agreement_form_idintegerNoLegacy single-form equivalent of quote_agreement_form_ids
sourcestringNoCustom source label (default: API)
notesstringNoInternal notes (max 5000 chars)
Creating does not send

A new quote starts in the draft state and the customer is not contacted. Call Send Quote to email the customer their private link.

Request Exampleโ€‹

curl -X POST "https://app.equipdash.com/api/v1/quotes" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_id": 456,
"booking_type": "rental",
"start_date": "2026-02-15T09:00:00Z",
"end_date": "2026-02-17T17:00:00Z",
"products": [
{ "product_id": 1, "quantity": 2 }
],
"quote_reserves": true,
"quote_valid_until": "2026-03-01",
"quote_agreement_form_ids": [12, 15]
}'

Responseโ€‹

Returns 201 Created with the complete quote โ€” see Quotes Overview โ†’ The Quote Object. state is draft and customer_url is null until the quote is sent.

{
"data": {
"id": 123,
"quote_number": "Q-123",
"state": "draft",
"reserves_dates": true,
"valid_until": "2026-03-01",
"sent_at": null,
"viewed_at": null,
"decided_at": null,
"decline_reason": null,
"agreements": [
{ "form_id": 12, "form_name": "Rental Agreement", "signed": false, "signed_at": null },
{ "form_id": 15, "form_name": "Liability Agreement", "signed": false, "signed_at": null }
],
"agreement": {
"form_id": 12,
"form_name": "Rental Agreement",
"signed": false
},
"customer_url": null,
"type": "rental",
"start_date": "2026-02-15T09:00:00+00:00",
"end_date": "2026-02-17T17:00:00+00:00",
"currency": "USD",
"pricing": {
"subtotal": 205.00,
"total": 225.50
},
"customer": {
"id": 456,
"first_name": "Jane",
"last_name": "Doe",
"full_name": "Jane Doe",
"display_name": "Jane Doe",
"email": "jane@example.com"
},
"products": [
{
"id": 45,
"product_id": 1,
"product_name": "Mountain Bike",
"variation_id": null,
"variation_name": null,
"bundle_in_booking_id": null,
"quantity": 2,
"price": 120.00
}
],
"experiences": [],
"bundles": [],
"store_products": [],
"created_at": "2026-02-01T10:00:00+00:00",
"updated_at": "2026-02-01T10:00:00+00:00"
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-02-01T10:00:00+00:00"
}
}

Holding datesโ€‹

With quote_reserves: true the quoted items and spots are blocked from other bookings until the customer decides โ€” availability is checked and reserved at creation time, exactly as it would be for a booking. With quote_reserves: false (the default) availability stays open; if the dates are taken before acceptance, Accept Quote returns 409 dates_unavailable.

Error Responsesโ€‹

Invalid customerโ€‹

{
"error": {
"code": "validation_error",
"message": "The given data was invalid.",
"details": [
{
"field": "customer_id",
"message": "The selected customer does not belong to your account."
}
]
}
}

Creation failureโ€‹

Bad line-item ids or (for a reserving quote) unavailable dates return 422 with code quote_creation_failed and a message describing the problem.

StatusCodeDescription
401authentication_requiredMissing or invalid API key
403insufficient_scopeAPI key lacks quotes:write scope
422validation_errorInvalid request body (bad dates, unknown agreement form, etc.)
422quote_creation_failedThe quote could not be built (bad ids, unavailable dates for a reserving quote)