Quotes let you send a priced proposal to a client before committing to an invoice. Once a client accepts a quote, you can convert it to an invoice in one step.
Quote statuses: draft · sent · accepted · declined · expired · converted
List quotes
GET /quote
Returns active quotes (draft and sent) by default.
| Query parameter | Type | Description |
|---|---|---|
| include_accepted | boolean | Include accepted quotes (default: false) |
| include_declined | boolean | Include declined quotes (default: false) |
| include_expired | boolean | Include expired quotes (default: false) |
| include_converted | boolean | Include converted quotes (default: false) |
Response:
{
"quotes": [
{
"id": "q001",
"number": "Q0001",
"status": "sent",
"client_id": "xyz789",
"currency": "ZAR",
"quote_date": "2026-03-01T00:00:00Z",
"expiry_date": "2026-03-31T00:00:00Z",
"amount": 150000,
"items": [...]
}
]
}Get a quote
GET /quote/:id
Returns a single quote by ID.
Find a quote by external reference
GET /quote/by_external_ref?ref=
Looks up a quote by the external_ref you supplied when creating it, to check for an existing quote before creating a duplicate. Returns 404 if none matches.
curl "https://api.rebill.co.za/quote/by_external_ref?ref=booklink:booking:abc123" \ -H "Authorization: Bearer sk_your_secret_key"
Quote object
| Field | Type | Description |
|---|---|---|
| id | string | Unique identifier |
| public_id | string | Short ID used in public-facing quote links |
| created | timestamp | When the quote was created |
| number | string | Human-readable quote number (e.g. Q0001) |
| currency | string | ISO 4217 currency code |
| vat_enabled | boolean | Whether VAT is shown on the quote |
| status | string | draft · sent · accepted · declined · expired · converted |
| client_id | string | ID of the client this quote belongs to |
| owner_user_id | string | ID of the team member this quote is attributed to |
| quote_date | timestamp | Quote issue date |
| expiry_date | timestamp | Date after which the quote expires |
| accepted_at | timestamp | When the client accepted (if applicable) |
| declined_at | timestamp | When the client declined (if applicable) |
| items | array | Line items (same structure as invoice items) |
| amount | integer | Total quote amount in cents |
| notes | string | Notes printed on the quote |
| converted_to_invoice_id | string | ID of the resulting invoice if converted |
| bank_details | string | Bank details (optional) |
| deposit_type | string | fixed or percentage (if applicable) |
| deposit_value | integer | Cents (fixed) or basis points (percentage) |
| deposit_amount | integer | Calculated deposit amount in cents |
| custom_fields | object | Key-value pairs of custom fields |
| external_ref | string | Caller-supplied reference for cross-system deduplication |
| accepted_terms_text | string | Snapshot of the terms text the client accepted, if any |
| next_follow_up_date | timestamp | Scheduled follow-up date, if set |
| last_followed_up_at | timestamp | When this quote was last marked as followed up |
| internal_notes | array | Operator-only notes; never shown to the client |
| labels | array | Internal organisation labels (strings); never shown to the client |
Create a quote
POST /quote
| Field | Required | Type | Description |
|---|---|---|---|
| client_id | Yes | string | ID of an existing client |
| quote_date | Yes | date | Quote issue date |
| expiry_date | Yes | date | Quote expiry date |
| items | Yes | array | At least one line item |
| currency | No | string | ISO 4217 code; defaults to the client, then account, default currency |
| notes | No | string | Notes to print on the quote |
| bank_details | No | string | Bank account details |
| deposit_type | No | string | fixed or percentage |
| deposit_value | No | integer | Cents (fixed) or basis points (percentage) |
| custom_fields | No | object | Additional key-value fields to display |
| external_ref | No | string | Caller-supplied reference, max 200 characters |
| owner_user_id | No | string | ID of the team member to attribute this quote to; defaults to the caller |
| labels | No | array | Internal organisation labels, up to 10 per quote, 40 characters each |
curl -X POST https://api.rebill.co.za/quote \
-H "Authorization: Bearer sk_your_secret_key" \
-H "Content-Type: application/json" \
-d '{
"client_id": "xyz789",
"quote_date": "2026-03-15",
"expiry_date": "2026-04-15",
"items": [
{
"type": "service",
"name": "Consulting",
"description": "Strategy session (2 hours)",
"quantity": 2,
"unit_price": 75000,
"vat_type": "standard",
"vat_rate": 1500
}
]
}'Response (201 Created):
{
"id": "q001"
}Update a quote
PUT /quote/:id
Updates an existing quote. draft, sent and expired quotes can be edited. accepted, declined and converted quotes are final and return 422 Unprocessable. Editing never changes the quote's status, so a quote you have already sent stays sent: resend it if you want the client to see the new version.
Pass number to renumber a draft; it must be unique on the account (400 with a number validation error otherwise). A sent or later quote refuses a number change with 422 because the client already has that number. Saving also refreshes the quote's VAT flag from the account, so a quote created before the business saved its VAT number picks VAT up on its next edit.
Delete a quote
DELETE /quote/:id
Permanently deletes a quote. Returns 200 OK on success.
Update quote labels
PUT /quote/:id/labels
Replaces the quote's internal label list. Works on any status - labels are operator-only metadata and nothing else on the quote changes.
| Field | Required | Type | Description |
|---|---|---|---|
| labels | Yes | array | Full replacement list of label strings, up to 10, 40 characters each |
curl -X PUT https://api.rebill.co.za/quote/q001/labels \
-H "Authorization: Bearer sk_your_secret_key" \
-H "Content-Type: application/json" \
-d '{
"labels": ["vip"]
}'Send a quote
POST /quote/:id/send
Sends the quote to the client by email and marks it as sent. Add ?whatsapp=true to send via WhatsApp instead.
# Send via email curl -X POST https://api.rebill.co.za/quote/q001/send \ -H "Authorization: Bearer sk_your_secret_key" # Send via WhatsApp curl -X POST "https://api.rebill.co.za/quote/q001/send?whatsapp=true" \ -H "Authorization: Bearer sk_your_secret_key"
Mark a quote as sent
POST /quote/:id/mark_as_sent
Marks a draft quote as sent without sending any notification. Use this when you've shared the quote through another channel.
List quotes due for follow-up
GET /quote/follow-ups
Returns open (draft or sent) quotes for a follow-up worklist, with client names and owner emails resolved.
| Query parameter | Type | Description |
|---|---|---|
| owner | string | me (default, the calling user's own quotes), all, or a specific team member's user ID |
curl "https://api.rebill.co.za/quote/follow-ups?owner=all" \ -H "Authorization: Bearer sk_your_secret_key"
Set a quote follow-up date
PUT /quote/:id/follow-up
Sets or clears the quote's scheduled follow-up date.
| Field | Required | Type | Description |
|---|---|---|---|
| next_follow_up_date | No | timestamp | New follow-up date, or omit/null to clear it |
curl -X PUT https://api.rebill.co.za/quote/q001/follow-up \
-H "Authorization: Bearer sk_your_secret_key" \
-H "Content-Type: application/json" \
-d '{
"next_follow_up_date": "2026-04-01"
}'Mark a quote as followed up
POST /quote/:id/mark-followed-up
Stamps the quote as followed up now, clears any scheduled follow-up date, and records an internal note (defaults to "Followed up" if you don't supply one).
| Field | Required | Type | Description |
|---|---|---|---|
| note | No | string | Internal note text; defaults to "Followed up" |
curl -X POST https://api.rebill.co.za/quote/q001/mark-followed-up \ -H "Authorization: Bearer sk_your_secret_key"
Add an internal note
POST /quote/:id/internal-note
Appends an internal note to the quote, attributed to the calling user. Internal notes are operator-only and never shown to the client.
| Field | Required | Type | Description |
|---|---|---|---|
| text | Yes | string | Note text |
curl -X POST https://api.rebill.co.za/quote/q001/internal-note \
-H "Authorization: Bearer sk_your_secret_key" \
-H "Content-Type: application/json" \
-d '{
"text": "Client asked for a 10% discount, following up Friday"
}'Convert a quote to an invoice
POST /quote/:id/convert
Converts an accepted quote (or a sent quote, if you want to convert before the client responds) into a draft invoice. The quote status changes to converted and the response contains the new invoice ID. Returns 422 Unprocessable if the quote is in another status or has already been converted.
| Field | Required | Type | Description |
|---|---|---|---|
| due_date | Yes | date | Due date for the resulting invoice |
curl -X POST https://api.rebill.co.za/quote/q001/convert \
-H "Authorization: Bearer sk_your_secret_key" \
-H "Content-Type: application/json" \
-d '{
"due_date": "2026-04-15"
}'Response:
{
"invoice_id": "inv001"
}Recreate the invoice for a converted quote
POST /quote/:id/recreate_invoice
Repair endpoint for a converted quote whose linked invoice was deleted. Rebuilds the invoice from the quote's current line items, deposit, and custom fields, and re-links the quote to it. Any ledger credit that funded the deleted invoice is released and automatically re-applied to the new one. Returns 422 Unprocessable if the quote isn't converted, or if the linked invoice still exists (this is a repair for a missing invoice only, not a way to duplicate one).
| Field | Required | Type | Description |
|---|---|---|---|
| due_date | No | date | Due date for the recreated invoice; defaults to 30 days from now |
curl -X POST https://api.rebill.co.za/quote/q001/recreate_invoice \ -H "Authorization: Bearer sk_your_secret_key"
Response (201 Created):
{
"invoice_id": "inv002"
}Reinstate a quote
POST /quote/:id/reinstate
Reinstates an expired quote - or a sent quote that has simply passed its expiry date - back to sent status with a new expiry date, allowing the client to reconsider. Not available for declined quotes.
| Field | Required | Type | Description |
|---|---|---|---|
| expiry_date | Yes | date | New expiry date; must be today or later |
curl -X POST https://api.rebill.co.za/quote/q001/reinstate \
-H "Authorization: Bearer sk_your_secret_key" \
-H "Content-Type: application/json" \
-d '{
"expiry_date": "2026-05-01"
}'List notifications for a quote
GET /quote/:id/notification
Returns the delivery history (email and WhatsApp sends) recorded for this quote, alongside delivery/engagement state for tracked emails. Same response shape as the invoice notification log.
curl https://api.rebill.co.za/quote/q001/notification \ -H "Authorization: Bearer sk_your_secret_key"