Skip to content

Offer ​

Allowed query parameters ​

Filters ​

FilterTypeDescription
searchStringFull-text search
projectIdFilter by Project Id
companyStringFilter by Company Id
statusStringFilter based on status:
approved, archived, pending, draft, approved_or_pending, billable
memberIdFilter by Member Id
custom_fieldKey,StringFilter by Custom Field (eg. my_internal_id,42)
trashedBooleanInclude soft-deleted offers

Sorting ​

name, created_at, approved_at

Includes ​

project, project.offers, contact.company.media, company.media, elements.tag, elements.product, member.user.media, createdBy.user.media, updatedBy.user.media, activities, sourcedInvoices, commentsCount, comments.commentator.media, media, latestOutgoingMail

Create an offer ​

post
/offer
Attribute (* required)TypeDescription
nameString?Offer title (max 255 characters)
project_idString?A Project Id (min 10 characters). For a sub-project, its parent is assigned
contact_id *StringA Contact Id (min 10 characters)
locked_atDate?Locked date
approved_atDate?Approved date
addressString?Recipient Address
headerString?Header text
footerString?Footer text
has_page_break_after_headerBooleanAdd page break after header
has_page_break_before_footerBooleanAdd page break before footer
descriptionString?Offer description
custom_fieldsObject?Custom data as Custom Fields

Example response ​

json
// HTTP 201 Created
{
    // an offer object
}

Update an offer ​

put
/offer/{id}
Attribute (* required)TypeDescription
nameString?Offer title (max 255 characters)
project_idString?A Project Id (min 10 characters). For a sub-project, its parent is assigned
contact_idStringA Contact Id (min 10 characters)
locked_atDate?Locked date
approved_atDate?Approved date
addressStringRecipient Address
headerString?Header text
footerString?Footer text
has_page_break_after_headerBooleanAdd page break after header
has_page_break_before_footerBooleanAdd page break before footer
descriptionString?Offer description
custom_fieldsObject?Custom data as Custom Fields

Example response ​

json
// HTTP 200 OK
{
    // an offer object
}

Retrieve an offer ​

get
/offer/{id}

Example response ​

json
// HTTP 200 OK
{
    "id": "EO6YGvqMRV",
    "number": "A-01025",
    "name": "CMS Upgrade",
    "description": null,
    "address": "<p><strong>StrawBlond</strong><br> Alice Cooper<br>R\u00fctistrasse 2<br>CH-8645 Rapperswil</p>",
    "header": "<p>Sehr geehrte Damen und Herren</p><p>Vielen Dank f\u00fcr Ihr Interesse</p>",
    "footer": "<p>Vielen Dank f\u00fcr eine fristgerechte Zahlung.</p><p>Freundliche Gr\u00fcsse<br>StrawBlond GmbH</p>",
    "has_page_break_after_header": false,
    "has_page_break_before_footer": false,
    "approved_at": "2022-02-09T08:51:59.000000Z",
    "archived_at": null,
    "archived_reason": null,
    "locked_at": "2022-02-09T08:51:59.000000Z",
    "is_approved": true,
    "is_archived": false,
    "is_locked": true,
    "address_personalized": "<p><strong>StrawBlond</strong><br> Alice Cooper<br>Rütistrasse 2<br>CH-8645 Rapperswil</p>",
    "header_personalized": "<p>Sehr geehrte Damen und Herren</p><p>Vielen Dank für Ihr Interesse</p>",
    "footer_personalized": "<p>Vielen Dank für eine fristgerechte Zahlung.</p><p>Freundliche Grüsse<br>StrawBlond GmbH</p>",
    "project": {
        // Project object when included
    },
    "contact": {
        // Contact object when included
    },
    "member": {
        // Member object when included
    },
    "created_by": {
        // Member object when included
    },
    "updated_by": {
        // Member object when included
    },
    "company": {
        // Company object when included
    },
    "elements": [
        // Only present when included `elements` relation
        {
            // a document element object
        }
    ],
    "total": 5640.0,
    "total_with_vat": 5640.0,
    "total_optional": 0.0,
    "show_vat": true,
    "vat_detailed": {
        "0.0": {
            "rate": 0.0,
            "net": 5640.0,
            "tax": 0.0
        }
    },
    "pdf_url": "http://localhost:8000/api/offer/EO6YGvqMRV/pdf?expires=1666341757&signature=331e3d4442bb23f4f9803fa56d27f581127836c240fd5b46917b7a33769f6c60",
    "order_confirmation_pdf_url": "http://localhost:8000/api/offer/EO6YGvqMRV/pdf?expires=1666341757&options%5Border_confirmation%5D=1&signature=abc123",
    "preview_url": "http://localhost:8000/api/offer/339/view?signature=686f2f15cda2a5d95657e463ac550aba7be9465ad80cca2787da11c8e04244e7",
    "approve_url": "http://localhost:8000/api/offer/EO6YGvqMRV/approve?expires=1666341757&signature=cb1b209e99bad2a7c18cc6b48d0f2123ad4cc3f6a47e0309b21be074218c58f9",
    "archive_url": "http://localhost:8000/api/offer/EO6YGvqMRV/archive?expires=1666341757&signature=67280f02330d155611a9694f73726df64628c7c13b5f34f369abbf89ed5fddc1",
    "share_url": "http://localhost:3000/q/hX8mT2qL9vRk4nW7cB3d",
    "mail_preview_url": "https://api.blond.swiss/api/document/mail-preview?type=offer&id=EO6YGvqMRV",
    "show_terms": true,
    "show_signature": false,
    "activities": [
        // Only present when included `activities` relation
    ],
    "sourced_invoices": [
        // Only present when included `sourcedInvoices` relation
    ],
    "billable_total": 5640.0,
    "billed_total": 0.0,
    "organization": {
        // Organization object when included
    },
    "comments": [
        // Only present when included `comments` relation
    ],
    "comments_count": 3, // Only present when included `commentsCount`
    "attachments": [
        // Only present when included `media` relation
    ],
    "latest_outgoing_mail": {
        // Only present when included `latestOutgoingMail` relation, see Delivery status
    },
    "custom_fields": {},
    "updated_at": "2022-02-09T08:52:00.000000Z",
    "created_at": "2021-12-09T09:05:28.000000Z",
    "deleted_at": null
}

Delivery status ​

Include latestOutgoingMail to see whether the last email sent for the offer reached its recipients. It has the same shape as on invoices, is null when the offer was never emailed, and is only returned when the API user may see the outgoing mail log.

Delete an offer ​

delete
/offer/{id}

Example response ​

json
// HTTP 204 No Content

Delete many offers ​

post
/offer/delete-many

Deletes multiple offers at once. The request body is a JSON array of offer ids. Returns 200 OK with deleted and skipped arrays — see Bulk delete.

List offers ​

get
/offer

The list endpoint accepts the same parameters as in Retrieve an offer and returns a paginated array of the same offer object in the data property.

Read more about Pagination, Filtering, Sorting and Includes on the Introduction page.

Offer line items ​

You may use the Document Element endpoint to create, update or delete line items on an offer.

Line items of a locked offer (is_locked: true) are frozen — see Locked documents.

Add products to an offer ​

post
/offer/{id}/add-products
Attribute (* required)TypeDescription
products *ArrayArray of Product IDs to add to the offer
beforeOrderNumber?Order position to insert products before (if not provided, adds to the end)

Fails with 422 Unprocessable Entity when the offer is locked.

Example request ​

json
{
    "products": ["6k2KpJY3By", "8m3LqKZ4Cx"],
    "beforeOrder": 2
}

Example response ​

json
// HTTP 200 OK
{
    // an offer object
}

Send an offer ​

post
/offer/{id}/send
Attribute (* required)TypeDescription
emailString | ArrayList of emails, as an array or a string separated by ";" (max. 5, Default: Contact email)
messageString?A short message to the recipients (max. 5000 characters, links are removed)
ccToOwnerBooleanSend a carbon copy to self
attachmentsArrayArray of media UUIDs to attach to the offer

Sending limits

A document can be sent to at most 5 recipients per request. Organizations without a paid subscription are limited to 10 recipient deliveries per day across all invoices and offers; exceeding either limit returns 422 Unprocessable Entity with a descriptive message.

No recipient

When no recipients are given and the offer's contact has no email address, there is nobody to send to: the request fails with 422 Unprocessable Entity and a descriptive message, and the offer is left unchanged (not locked, not marked as sent).

Test mode without a subscription

Without an active paid subscription, documents are not delivered to the given recipients: the email is redirected to the sending user's own (verified) email address instead and carries a notice naming the original recipients. The response is still 200 OK and the document is marked as sent.

Example response ​

json
// HTTP 200 OK
{
    // an offer object
}