Create and send quotes
Learn how to create a quote and send a formal offer.
Overview
A quote is a formal offer that details how much a product or service will cost.
Quotes are similar to invoices. The difference is that a quote is given to a potential customer before they decide to purchase, whereas an invoice is issued after the delivery of products or services to the customer.
Quotes have an expiry date by which the quote should be accepted or declined.
Create a quote
A typical quote workflow includes the following steps:
- Create a counterpart that represents the customer.
- Create one or more products to be listed in the quote.
- Get the applicable VAT rates based on the entity's country and the counterpart's country, and choose the rates for the products that will be listed in the quote.
- Create the quote.
- Download a PDF of the created quote. (Optional)
- Send the quote via email.
- Create an invoice based on the quote. (Optional)
1. Create a counterpart
The counterpart represents the customer (organization or individual) purchasing your products or services.
Learn how to create counterparts.
2. Create a product
The products to be listed in the quote must also be created in advance, as well as their respective measure units.
Learn how to create products and measure units.
As an example, here is a representation of a sample t-shirt product:
{
"id": "8755c86a-d630-4920-b6fd-fd2917d87dfb",
"name": "T-shirt",
"type": "product",
"description": "A black cotton t-shirt, medium size",
"price": {
"currency": "EUR",
"value": 1000 // 10 Euro
},
"measure_unit_id": "256560f1-8d09-4d21-aadf-45b33e4b0660",
"smallest_amount": 1
}
The associated measure unit is "pieces" (items):
{
"id": "256560f1-8d09-4d21-aadf-45b33e4b0660",
"name": "pcs",
"description": "pieces",
...
}
3. Get VAT rates
A quote must specify VAT rates for its line items, even if the VAT is 0%. You can call GET /vat_rates?counterpart_id={id}
to get the possible VAT rates for sales to the given counterpart:
curl 'https://api.sandbox.monite.com/v1/vat_rates?counterpart_id=0414f...5435' \
-H 'X-Monite-Entity-Id: ENTITY_ID' \
-H 'Authorization: Bearer ACCESS_TOKEN'
The response includes the possible VAT rates (as a percentage multiplied by 100) and their IDs. Store the IDs somewhere as you will need them later.
{
"data": [
{
"id": "a39a2ec3-765d-4f75-9a17-585a5d22509d",
...
"value": 0,
"country": "DE"
},
{
"id": "51cefc6c-9f82-484e-ae6a-a3a89b507bea",
...
"value": 700,
"country": "DE"
},
...
]
}
Learn more about VAT rates.
4. Create the quote
Once the counterpart and products have been created, you can create the quote for a given counterpart by calling POST /receivables
.
The request body must contain the counterpart ID, line items (products, their quantities, and VAT rates), and quote expiration date, among other information. The subtotal, total, and VAT amount are not specified in the request - they will be calculated automatically based on the product price, quantity, and VAT rates.
The example below creates a quote for five items of a product:
curl -X POST 'https://api.sandbox.monite.com/v1/receivables' \
-H 'X-Monite-Entity-Id: ENTITY_ID' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"type": "quote",
"counterpart_id": "0414f84c-b039-4203-b09b-e42b49245435",
"expiry_date": "2022-06-01",
"currency": "EUR",
"line_items": [
{
"product_id": "8755c86a-d630-4920-b6fd-fd2917d87dfb",
"quantity": 5,
"vat_rate_id": "479155c3-0995-4689-a3cf-7482ea5132a9"
}
],
"vat_exempt": false,
"entity_bank_account": {
"bank_name": "Omega Bank",
"iban": "9128309180391",
"bic": "18239012"
}
}'
The successful 201 Created
response contains the id
assigned to the created quote, along with the calculated total (total_amount
), subtotal (subtotal
), VAT (total_vat_amount
), and other information.
{
"type": "quote",
"expiry_date": "2022-06-01",
"id": "e9a25ceb-003d-4c82-9e90-5d568ccd8c47",
"created_at": "2022-05-04T09:12:53.875094+00:00",
"updated_at": "2022-05-04T09:12:53.875103+00:00",
"currency": "EUR",
"subtotal": 5000,
"line_items": [
{
"quantity": 5,
"product": {
...
}
}
],
"total_amount": 5900,
"total_vat_amount": 950,
...
}
For the complete list of quote data fields and their descriptions, refer to the
/receivables
endpoint.
5. Download the quote as PDF
Monite automatically generates the PDF version of quotes. The PDF file details - URL, file size, MD5 hash, and other information - are returned in the file
field of quote responses:
{
"type": "quote",
...
"file": {
...
"md5": "31d1a2dd1ad3dfc39be849d70a68dac0",
"url": "https://bucketname.s3.amazonaws.com/12345/67890.pdf",
"size": 24381,
...
},
...
}
If
file
is returned asnull
, repeat the request toGET /receivables/{quote_id}
after some time.
If you need just the PDF file link without the full quote details, call GET /receivables/{quote_id}/pdf_link
:
curl 'https://api.sandbox.monite.com/v1/receivables/b21c80...8ad9/pdf_link' \
-H 'X-Monite-Entity-Id: ENTITY_ID' \
-H 'Authorization: Bearer ACCESS_TOKEN'
It returns the following response:
{
"file_url": "https://bucketname.s3.amazonaws.com/12345/67890.pdf"
}
Here's how the PDF looks like:
The PDF file is updated automatically if the quote is changed (for example, if new line items are added to a draft quote, or if the counterpart address is changed).
Customize the PDF quote
Monite provides several built-in PDF templates for quotes. The preferred template can be set in the entity settings.
6. Send the quote via email
Once a draft quote has been prepared, you can send it to the customer via email. To do this, call POST /receivables/{quote_id}/send
and provide the email subject and body templates. The quote will be attached as a PDF file to the email.
curl -X POST 'https://api.sandbox.monite.com/v1/receivables/e9a25c...8c47/send' \
-H 'X-Monite-Entity-Id: ENTITY_ID' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"subject": "New quote #{quote_number}",
"body": "Dear {contact_name},\n\nThank you for requesting a quote for your project. We are happy to provide you with our quote #{quote_number}!\n\nIf you have any questions, please don't hesitate to contact us at {entity_email}."
}'
The To
email address is taken from the Counterpart
object associated with the quote. This address is also returned in the counterpart_contact.email
field of the Receivable
object that represents the quote.
The From
email address is [email protected]<entity_name>.monite.com
(currently not customizable).
The {variables}
in the email content will be substituted with the corresponding values from the quote data and counterpart data. The supported variables are:
Variable | Description |
---|---|
{company_email} | The email address of the counterpart. |
{company_name} | The counterpart name (either the company name or an individual's name). |
{contact_email} | The email address of the counterpart's default contact. If no contacts are defined, the counterpart's email address is used instead. Note: This variable exists only if the counterpart is an organization. |
{contact_name} | The name of the counterpart's default contact. If no contacts are defined, the counterpart name is used instead. Note: This variable exists only if the counterpart is an organization. |
{entity_email} | The email address of the entity that created the quote. |
{entity_name} | The name of the entity that created the quote. |
{fulfilled_date} | Unused. |
{issue_date} | The date when the quote was issued. |
{payment_link} | Unused. |
{quote_link} | A link to the PDF version of the quote, as returned by the file_url property of the Receivable object. |
{quote_number} | The quote number, as returned by the document_id value of the Receivable object. |
{total_value} | The quote subtotal (without VAT), formatted with cents but without the currency sign. For example, $50 is represented as 50.00 . |
A 200 OK
response from POST /receivables/{quote_id}/send
means the email was successfully sent from the Monite email server.
Sending a quote changes its status from
draft
toissued
. Issued quotes can no longer be edited.
Resend the quote
To resend an already issued quote, you can call POST /receivables/{quote_id}/send
again, optionally with different subject_text
and body_text
templates.
Resending a quote does not change its
status
.
7. Accept or decline the quote
If the customer accepted the quote, call POST /receivables/{quote_id}/accept
to mark the quote as accepted
. Note that this request requires an empty object {}
in the request body.
curl -X POST 'https://api.sandbox.monite.com/v1/receivables/e9a25c...8c47/accept' \
-H 'X-Monite-Entity-Id: ENTITY_ID' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{}'
If the customer declined the quote, call POST /receivables/{quote_id}/decline
to mark the quote as declined
. As a best practice, customers should provide a reason why they declined the quote. This reason can be specified in the comment
field in the request body:
curl -X POST 'https://api.sandbox.monite.com/v1/receivables/e9a25c...8c47/decline' \
-H 'X-Monite-Entity-Id: ENTITY_ID' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"comment": "Thanks for the quote, but we decided to go with another vendor."}'
7. Create an invoice based on the quote
If the customer accepted the quote, you can create an invoice based on this quote after the goods or services have been delivered. Invoices can be created from quotes in the draft
, issued
, and accepted
states.
To create an invoice from a quote, call POST /receivables
and provide the quote ID in the based_on
field in the request body:
curl -X POST 'https://api.sandbox.monite.com/v1/receivables' \
-H 'X-Monite-Entity-Id: ENTITY_ID' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"type": "invoice",
"based_on": "e9a25ceb-003d-4c82-9e90-5d568ccd8c47"
}'
This creates a new draft invoice with a copy of the quote data (that is, with the same line items and counterpart). The ID and document number of the original quote are saved in the based_on
and based_on_document_id
properties, respectively.
{
"type": "invoice",
"id": "b21c80f9-18c0-40ce-be6b-89ddcc4d8ad9",
"created_at": "2022-05-19T06:04:29.499753+00:00",
"updated_at": "2022-05-19T06:04:30.976539+00:00",
"currency": "EUR",
"subtotal": 5000,
"total_amount": 5900,
"line_items": [ ... ],
...
"status": "draft",
"based_on": "e9a25ceb-003d-4c82-9e90-5d568ccd8c47",
"based_on_document_id": "#receivable--00015",
"payment_terms": null
}
Next, add payment terms to the created invoice. The payment terms define the invoice due date and, optionally, early payment discounts.
curl -X PATCH 'https://api.sandbox.monite.com/v1/receivables/b21c80...8ad9' \
-H 'X-Monite-Entity-Id: ENTITY_ID' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"invoice": {
"payment_terms_id": "411d9079-02af-476d-8723-4789882e01c3"
}
}'
The invoice due date is calculated automatically based on the creation date and payment terms and is returned in the payment_terms.term_final.end_date
property in the response.
{
"type": "invoice",
"id": "b21c80f9-18c0-40ce-be6b-89ddcc4d8ad9",
"created_at": "2022-05-19T06:04:29.499753+00:00",
...
"payment_terms": {
"id": "411d9079-02af-476d-8723-4789882e01c3",
"name": "Net 30",
"description": "The payment is due within 30 days after the invoice issue date.",
"term_final": {
"number_of_days": 30,
"end_date": "2022-06-18"
}
}
}
Next, you can download the invoice as PDF and send it to the customer via email.
Quote expiration
After a quote's expiry_date
has passed, the quote status automatically becomes expired
. Expired quotes cannot be accepted or declined. If needed, you can create a fresh quote for the same counterpart.
List all quotes
To get a list of all quotes generated by an entity, call GET /receivables?type=quote
:
curl 'https://api.sandbox.monite.com/v1/receivables?type=quote' \
-H 'X-Monite-Entity-Id: ENTITY_ID' \
-H 'Authorization: Bearer ACCESS_TOKEN'
You can sort and filter the results by the amount, counterpart name, and other fields. For the full list of available sort and filter parameters, see the description of the GET /receivables
endpoint.
Some examples:
GET /receivables?type=quote&counterpart_name=Acme%20Inc.
- get all quotes issued to Acme Inc.GET /receivables?type=quote&amount__gte=15000
- get all quotes where the total amount is €150 or more.GET /receivables?type=quote&status__in=draft&status__in=issued
- get all draft and issued quotes.GET /receivables?type=quote&created_at__gte=2022-01-01T00%3A00%3A00
- get all quotes created on or after January 1, 2022.
Retrieve a quote
To get information about a specific quote, call GET /receivables/{receivable_id}
and provide the quote ID.
Find invoices created from a quote
To check if there are invoices created from a specific quote, call GET /receivables?based_on=QUOTE_ID
:
curl 'https://api.sandbox.monite.com/v1/receivables?based_on=e9a25ceb-003d-4c82-9e90-5d568ccd8c47' \
-H 'X-Monite-Entity-Id: ENTITY_ID' \
-H 'Authorization: Bearer ACCESS_TOKEN'
The data
array in the response contains a list of related invoices, if any:
{
"data": [
{
"type": "invoice",
"id": "b21c80f9-18c0-40ce-be6b-89ddcc4d8ad9",
...
}
],
"prev_pagination_token": null,
"next_pagination_token": null
}
Updated about 2 months ago