Skip to main content

Manage proformas

A proforma is a preliminary document sent to a customer before a sale is confirmed. It outlines the expected cost of goods or services and gives the customer a chance to review and accept or decline the offer. Once accepted, a proforma can be converted directly into an invoice.

Proformas are also useful as invoice drafts. They can be freely updated or declined before you commit to converting them into a final, uneditable invoice.

You can find the full reference for all proforma operations in our API docs.

Lifecycle of a proforma

A proforma moves through the following states:

StateDescription
outstandingAwaiting a response from the customer (default).
lateThe valid_until date has passed with no response.
acceptedThe customer agreed to the proforma.
declinedThe customer rejected the proforma.
invoicedThe proforma has been converted into an invoice.

Create a proforma

Send a POST request to /proformas with the customer and line item details (more details here):

curl -u YOUR_API_KEY:x \
-H 'Content-Type: application/json' \
-X POST \
-d '{
"contact": {
"first_name": "Alex",
"last_name": "Wick",
"email": "[email protected]",
"street_line_1": "67 Church Lane",
"city": "London",
"postal_code": "E94 7RT",
"country": "GB"
},
"currency": "GBP",
"subject": "SaaS subscription — Q3 2025",
"valid_until": "2025-07-31",
"items": [
{
"description": "Professional Plan",
"quantity": 1,
"unit_price_cents": 9900,
"tax_1_transaction_type": "saas",
"tax_1_country": "GB"
}
],
"notes": "Prices are exclusive of VAT where applicable.",
"po_number": "PO-2025-001"
}' \
'https://ACCOUNT_NAME.quadernoapp.com/api/proformas.json'

A successful request returns a 201 Created response with the new proforma object:

{
"id": 92732431,
"number": "E-00001",
"state": "outstanding",
"issue_date": "2025-06-27",
"valid_until": "2025-07-31",
"currency": "GBP",
"subject": "SaaS subscription — Q3 2025",
"contact": {
"id": 229575,
"full_name": "Alex Wick"
},
"items": [
{
"description": "Professional Plan",
"quantity": 1.0,
"subtotal_cents": 9900
}
],
"subtotal_cents": 9900,
"discount_cents": 0,
"total_cents": 11880,
"taxes": [
{
"name": "VAT",
"rate": 20.0,
"amount_cents": 1980
}
],
"pdf": "https://quadernoapp.com/estimate/abc123.pdf",
"permalink": "https://quadernoapp.com/estimate/abc123",
"url": "https://ACCOUNT_NAME.quadernoapp.com/api/proformas/92732431.json"
}

The pdf and permalink fields give you direct links to share the document with your customer.

Retrieve a proforma

To fetch an existing proforma by its ID (more details here):

curl -u YOUR_API_KEY:x \
'https://ACCOUNT_NAME.quadernoapp.com/api/proformas/92732431.json'

List proformas

Retrieve a paginated list of all proformas, sorted by creation date (newest first) (more details here):

curl -u YOUR_API_KEY:x \
'https://ACCOUNT_NAME.quadernoapp.com/api/proformas.json'

You can narrow the results using query parameters:

ParameterDescriptionExample
qSearch by proforma number, customer name, or PO number.q=E-00001
dateFilter by issue date range (YYYY-MM-DD,YYYY-MM-DD).date=2025-01-01,2025-12-31
stateFilter by state: outstanding, accepted, declined, invoiced, late.state=outstanding
contactFilter by customer ID.contact=229575
curl -u YOUR_API_KEY:x \
'https://ACCOUNT_NAME.quadernoapp.com/api/proformas.json?state=outstanding&date=2025-01-01,2025-12-31'

Update a proforma

You can update a proforma as long as it is in outstanding or late state. Accepted and invoiced proformas cannot be modified (more details here):

curl -u YOUR_API_KEY:x \
-H 'Content-Type: application/json' \
-X PUT \
-d '{
"valid_until": "2025-08-31",
"notes": "Updated payment terms: net 30 days."
}' \
'https://ACCOUNT_NAME.quadernoapp.com/api/proformas/92732431.json'

Deliver a proforma

Send the proforma to your customer via email (more details here):

curl -u YOUR_API_KEY:x \
'https://ACCOUNT_NAME.quadernoapp.com/api/proformas/92732431/deliver.json'

Quaderno will email the proforma to the address on file for the contact. You can check the deliveries field in the proforma object to see the delivery history.

Manage the proforma response

Once you have delivered the proforma, you can update its state based on your customer's response.

Accept

Mark a proforma as accepted by the customer. Only proformas in outstanding or late state can be accepted (more details here):

curl -u YOUR_API_KEY:x \
-X PUT \
'https://ACCOUNT_NAME.quadernoapp.com/api/proformas/92732431/accept.json'

Decline

Mark a proforma as declined by the customer. Only proformas in outstanding or late state can be declined (more details here):

curl -u YOUR_API_KEY:x \
-X PUT \
'https://ACCOUNT_NAME.quadernoapp.com/api/proformas/92732431/decline.json'

Revert

Revert a proforma back to outstanding from accepted or declined. This is useful when you need to renegotiate terms. Invoiced proformas cannot be reverted (more details here):

curl -u YOUR_API_KEY:x \
-X PUT \
'https://ACCOUNT_NAME.quadernoapp.com/api/proformas/92732431/revert.json'

Convert a proforma into an invoice

Once a proforma is accepted, you can convert it into a final invoice. The proforma transitions to invoiced and a new invoice object is returned (more details here):

curl -u YOUR_API_KEY:x \
-X PUT \
'https://ACCOUNT_NAME.quadernoapp.com/api/proformas/92732431/convert.json'

The response will be the newly created invoice, ready to send to your customer.