---
title: "Create a proposal"
method: POST
path: "/api/v1/proposals"
tags: ["Proposals/Confirmed Bookings"]
---

# Create a proposal

`POST /api/v1/proposals`

## Request

- Base URL: `https://api.checkcherry.com`
- URL: `https://api.checkcherry.com/api/v1/proposals`
- Auth: none declared. Required headers: `Api-Key`

Creates a proposal -- an event the client still has to accept. For one they have already committed to, use `POST /api/v1/bookings`.

`proposal_date_reserved` decides what happens to the date while they decide. It defaults to `false`, leaving the date open to other bookings; send `true` to hold it for them. `proposal_valid_through` is the last day they can accept, and defaults to the business's own expiry setting. A date after the event is quietly pulled back to the event date; one in the past is rejected.

### Attaching the client

`contact_type` decides where the client comes from. It takes one of three exact strings -- anything else is rejected:

| `contact_type` | What it does |
| --- | --- |
| `New Customer` | The default. Creates the client from the `contact_*` fields, and `contact_name` is required. If `contact_email` matches someone the business already has, that person is linked rather than duplicated. |
| `Existing Customer` | Links a client who already exists. `customer_user_id` is required, and must be a user on this business. |
| `None` | Creates the proposal with nobody attached. |

Under `New Customer`, sending `contact_email` creates a full customer account the client can accept and pay through. Without one you get a plain contact record on the proposal instead, which can do neither.

The `contact_*` address fields hold the client's address. The venue address is separate, in the `venue_*` fields.

### Packages

`packages` is required -- a proposal with no package has nothing to price. Each entry needs an `event_type_id` (a package id from `GET /api/v1/packages`) and a `starts_at_date`. Send several to propose more than one package on the same event.

Pricing, tax, travel fees and the title are all calculated from the packages and the venue. Send `total_amount` only to override the calculated total.

### Dates, times and amounts

Dates are ISO `YYYY-MM-DD`. Other numeric formats are read according to the business's own date format setting, so `03-04-2027` is March 4th for a US business and April 3rd for an international one. Times take `11:00AM`, `2:30pm` or `14:30`.

Amounts are in the business's currency in whole units rather than cents, so `1250.00` is $1,250.00.

**Required permission:** `event_create` or `proposal_create`

## Headers

- `Api-Key` string, required

## Request body

- object
  - `proposal_date_reserved` boolean: Hold the date while the client decides, blocking other bookings. Defaults to `false`.
  - `proposal_valid_through` string: Last day the client can accept, as `YYYY-MM-DD`. Must not be in the past, and is capped at the event date. Defaults to the business's own expiry setting.
  - `contact_type` 'New Customer' | 'Existing Customer' | 'None': Where the client comes from. See the description above.
  - `customer_user_id` integer: The existing client's user ID, which must belong to this business. Required when `contact_type` is `Existing Customer`.
  - `contact_name` string: Client's name. Required when `contact_type` is `New Customer`.
  - `contact_email` string: Client's email. Creates a full customer account rather than a plain contact record.
  - `contact_phone` string: Client's phone
  - `contact_company_name` string: Client's company name
  - `contact_description` string: Client's role, e.g. "Bride" or "Father of the Groom"
  - `contact_street` string: Client's street address
  - `contact_city` string: Client's city
  - `contact_state_code` string: Client's state or province code, in whatever form the business's country uses, e.g. `MA`
  - `contact_postal_code` string: Client's postal code
  - `venue_name` string: Venue name
  - `venue_address` string: Venue street address
  - `venue_city` string: Venue city
  - `venue_state` string: Venue state or province code, in whatever form the business's country uses, e.g. `MA`
  - `venue_zip` string: Venue postal code
  - `venue_google_place_id` string: Google Place ID for the venue
  - `venue_latitude` number: Venue latitude
  - `venue_longitude` number: Venue longitude
  - `add_tax` boolean: Apply tax based on the venue's tax zone. Defaults to `true`.
  - `add_travel` boolean: Apply travel fees based on the venue's travel zone. Defaults to `true`.
  - `public_notes` string: Notes visible to the client
  - `private_notes` string: Notes only staff can see
  - `custom_title` string: Overrides the generated title
  - `brand_id` integer: Brand to propose under, which must be an active brand of this business. Defaults to the primary brand.
  - `lead_id` integer: Lead this proposal converts, from `GET /api/v1/leads`. The lead's details and attribution carry over and it is marked converted.
  - `total_amount` number: Overrides the calculated event total. In whole currency units, so `1250.00` means $1,250.00. Max 999000.
  - `paid_amount` number: Payment already collected outside Check Cherry, recorded against the proposal. In whole currency units. Max 999000.
  - `custom_deposit_amount` number: Overrides the calculated deposit due. In whole currency units, and capped at the event total. Max 999000.
  - `packages` object[], required: The packages being proposed. At least one is required.
    - `event_type_id` string, required: Package ID, from `GET /api/v1/packages`. Send the literal `custom` to price a one-off package instead, alongside `one_off_custom_title` and `total_amount`.
    - `starts_at_date` string, required: Start date, as ISO `YYYY-MM-DD`. Other numeric formats are read according to the business's date format setting.
    - `starts_at_time` string: Start time, e.g. `11:00AM`, `2:30pm` or `14:30`. Required for packages scheduled by date and time.
    - `ends_at_time` string: Overrides the end time implied by the length. Same formats as `starts_at_time`.
    - `length_in_minutes` integer: Length in minutes, from 1 to 1440. Required for packages that let extra hours be booked, otherwise defaults to the package's own length.
    - `length_in_days` integer: Length in days, from 1 to 1000. Required for packages that let extra days be booked.
    - `units` integer: Unit count, for packages priced per unit. Must fall inside one of that package's unit ranges, which are listed on `GET /api/v1/packages/{id}`.
    - `package_unit_range_id` integer: Unit range ID, for packages priced by unit range. Must be one of that package's own ranges, from `GET /api/v1/packages/{id}`.
    - `backdrop_id` integer: Backdrop ID, from `GET /api/v1/photobooth_backgrounds`
    - `add_on_ids` string: Comma-separated add-on IDs, e.g. `4,17`. Prefix an ID with a quantity to propose more than one: `2x17`.
    - `staff_id` integer: Staff member assigned to this package, who must belong to this business. Ignored when the package's service assigns staff automatically.
    - `one_off_custom_title` string: Title for a one-off package. Required when `event_type_id` is `custom`.
    - `custom_description_html` string: Description for a one-off package

## Response `200`

proposal created

## Other responses

- `422`: existing customer without customer_user_id

---

[API](https://skmtc.dev/checkcherry/apis/check-cherry-business-api.md) · [All operations](https://skmtc.dev/checkcherry/apis/check-cherry-business-api/llms.txt) · [OpenAPI document](https://skmtc.dev/checkcherry/apis/check-cherry-business-api/revisions/84a9aabdf519?raw)
