Attach images and notes

In this tutorial, you learn how to associate supplemental items such as a receipt image, product photo, or a note to an existing transaction or Item object. In QuickBooks Online, these supplemental items are called attachments.

Attachments are kept in a repository called the attachment list. This list is managed from both the QuickBooks Online user interface (via the Attachments List page) and the QuickBooks Online API (via the Upload and Download resources).  Each attachment has metadata associated with it, including information about its relationship to transaction or Item objects. Use the Attachable resource to manage metadata.

There are two types of attachments.

  • Note—Notes are added via the Attachable resource.
  • Files—Files are uploaded and related to the object via an Attachable object. Use this type of attachment when a separate file needs to be attached such as a receipt or photo. File attachments can include a note.

To follow along, you'll need a sandbox or another QuickBooks company populated with a chart of accounts, customers, and items. The examples in this tutorial use the sandbox company.

Attaching a note to an object

Operation:      POST https://quickbooks.api.intuit.com/v3/company/<realmID>/attachable
Content type: application/json

Request body

Here is a sample request body that adds a note to an Invoice.  The value attribute of the EntityRef below is the Id of the Invoice object retrieved from a previous fetch of the Invoice object.

Click to view sample.
 {     "AttachableRef": [
    {
      "EntityRef": {
        "type": "Invoice",
        "value": "95"
      }
    }
  ],
  "Note":"This is a note added to the invoice."
  }

Response body

An Attachable object is returned confirming that the note is now attached to the invoice.

Click to view sample.
{
    "Attachable": {
        "Note": "This is a note added to the invoice.",
        "domain": "QBO",
        "sparse": false,
        "Id": "100000000004191632",
        "SyncToken": "0",
        "MetaData": {
            "CreateTime": "2015-11-16T11:43:06-08:00",
            "LastUpdatedTime": "2015-11-16T11:43:06-08:00"
        },
        "AttachableRef": [{
            "EntityRef": {
                "value": "95",
                "type": "Invoice"
            },
            "IncludeOnSend": false
        }]
    },
    "time": "2015-11-16T11:43:06.064-08:00"
}

Attaching a file to an object

To attach a file to an existing object such as a supporting receipt to an invoice object or a photo to an item object, use the Attachable resource to link it to the object.

  • For new attachments: Link a new attachment by adding a Attachable metadata object to multipart payload for the upload operation. 
  • For existing attachments already in the Attachments list: Link the existing attachment via an update operation on the existing attachment's Attachable metadata object. 
Note
  • The attachment/object relationship is established with the Attachable object, only; the object does not include a link back to the attachment.
  • The object must already exist in order to add an attachment to it.

Uploading and linking new attachments

If the attachment is not in the Attachment list already, it's possible to upload it and link it to the object in one multipart operation.

Operation:      POST https://quickbooks.api.intuit.com/v3/company/<realmID>/upload
Content type: multipart/form-data

Request body

The following sample code shows the multipart request body for uploading a file and its supporting Attachable metatdata object, with the result of it being both added to the Attachment list and added to the object.

  • The Attachable object accompanying this request supplies metadata and object information to which the attachment is linked. 
  • Each part of the multipart request is separated by a boundary.  In the sample below, the string  --YOjcLaTlykb6OxfYJx4O07j1MweeMFem is used.  You can use any random and unique string.
  • The file to be uploaded and its Attachable object are paired together via the name parameter in the part header for each one.
    • The name parameter for the file part is of the form file_content_nn, where nn is a unique index number among the set of files being uploaded.
    • The name parameter for the Attachable object is of the form file_metadata_nn, where nn corresponds to the file index number used with the content .
  • The file or files are stored in the Attachment list with the name specified by the filename parameter.
  • If the data supplied with the Attachable object cannot be validated, an error is returned and the file is not uploaded.
Click to view sample.
--YOjcLaTlykb6OxfYJx4O07j1MweeMFem
Content-Disposition: form-data; name="file_metadata_01"; filename="attachment.json"
Content-Type: application/json 
{
    "AttachableRef": [
    {
      "EntityRef": {
        "type": "Invoice",
        "value": "95"
      }
    }
  ],
   "FileName": "receipt_nov15.jpg",
    "ContentType": "image/jpg"
  }
--YOjcLaTlykb6OxfYJx4O07j1MweeMFem
Content-Disposition: form-data; name="file_content_01"; filename="receipt_nov15.jpg"
Content-Type: image/jpeg
<insert base-64 encoded file content here>
--YOjcLaTlykb6OxfYJx4O07j1MweeMFem​--

Response body

An Attachable object is returned confirming that the file is now attached to the invoice.

Click to view sample.
{
  "AttachableResponse": [
    {
      "Attachable": {
        "FileName": "receipt_nov15.jpg",
        "FileAccessUri": "...",
        "TempDownloadUri": "https://...",
        "Size": 1594261,
        "ContentType": "image/jpeg",
        "ThumbnailFileAccessUri": "...",
        "domain": "QBO",
        "sparse": false,
        "Id": "100000000004190865",
        "SyncToken": "0",
        "MetaData": {
          "CreateTime": "2015-11-16T10:59:02-08:00",
          "LastUpdatedTime": "2015-11-16T10:59:02-08:00"
        },
        "AttachableRef": [
          {
            "EntityRef": {
              "value": "95",
              "type": "Invoice"
            },
            "IncludeOnSend": false
          }
        ]
      }
    }
  ],
  "time": "2015-11-16T10:58:58.100-08:00"
}

Linking existing attachments

Operation: POST https://quickbooks.api.intuit.com/v3/company/<realmID>/attachable
Content type:application/json

Request body

The sample request below shows how to link an existing attachment already in the Attachment list to an object, in this case an invoice.

Click to view sample request body.
{
     "AttachableRef": [
    {
      "EntityRef": {
        "type": "Invoice",
        "value": "95"
      }
    }
  ],
 "FileName": "receipt_june10.pdf"
  }

Response body

The result is the AttachableRef element of the existing Attachable object links a receipt already in the Attachments list to an Invoice object whose internal Id is 754, as shown in this image. Some field values have been abbreviated.

InvoiceAttachment.png

Click to view sample response body.
{
  "Attachable": {
    "FileName": "receipt_june10.pdf",
    "FileAccessUri": "...",
    "TempDownloadUri": "...",
    "Size": 1594261,
    "ContentType": "image/pdf",
    "ThumbnailFileAccessUri": "...",
    "ThumbnailTempDownloadUri": "https://...",
    "domain": "QBO",
   "sparse": false,
    "Id": "100000000004062175",
    "SyncToken": "1",
    "MetaData": {
      "CreateTime": "2015-10-29T16:04:05-07:00",
      "LastUpdatedTime": "2015-11-11T13:22:44-08:00"
    },
    "AttachableRef": [
      {
        "EntityRef": {
          "value": "95",
          "type": "Invoice"
        },
        "IncludeOnSend": false
      }
    ]
  },
  "time": "2015-11-11T13:22:44.013-08:00"
}

Listing attachments for a specific object

The relationship between an attachment and a transaction or item object resides in the Attachable metadata object for the attachment. It is possible to query the attachment list for the attachments linked to a particular object.

Issue the query below for all attachments linked to the purchase object whose Id is 611.

Operation: POST https://quickbooks.api.intuit.com/v3/company/<realmID>/query?query=<selectStmt>
Content type: text/plain

The sample select statement below returns the attachable ids for all attachments linked to the purchase object whose Id is 611. To formulate this statement, you must first know the type of object and its object Id using the query endpoint for that resource.

select Id from attachable where AttachableRef.EntityRef.Type = 'purchase' and AttachableRef.EntityRef.value = '611'

For your own request:

  • Set AttachableRef.EntityRef.type with the specific type of the target object. For this example, purchase is used.
  • Set AttachableRef.EntityRef.value with the Id of the target object as returned in its response body when queried. For this example, 611 is used.

Response body

This response returns two attachable objects corresponding to the two attachments to the target Purchase object. Use these Ids in other Attachable and Download resource operations as needed.

{
  "QueryResponse": {
    "Attachable": [
      {
        "sparse": true,
        "Id": "100000000004062174"
      },
      {
        "sparse": true,
        "Id": "100000000004158481"
      }
    ],
    "startPosition": 1,
    "maxResults": 2
  },
  "time": "2015-11-24T10:18:31.289-08:00"
}

Uploading files to the attachment list

Operation: POST https://quickbooks.api.intuit.com/v3/company/<realmID>/upload
Content type:multipart/form-data

This operation uploads one or more files to the Attachments list.

Of note:

  • The request must contain at least one file to upload.
  • A request can upload multiple files, up to a total size of 100MB.
  • The file-part header must specify the correct Content-Type. For example, if the file has a .jpg extension, make sure you send Content-Type:image/jpeg as the file part's content type.
  • The response body returns an Attachable object for each successful upload or a Fault object for failed upload attempt.
  • Thumbnails are automatically generated for image files. Thumbnail URIs are returned in the Attachable object via the ThumnailFileAccessUri attribute.

Request body

The following sample code shows the multipart request body for uploading two files: the image, receipt_oct29.jpg, and the PDF file, receipt_june10.pdf.

  • There is no metadata accompanying this request so default metadata is created by the data service and returned in the response body.
  • The value of the name parameter is in the form file_content_nn, where nn is a unique index number among the set of parts submitted in the multipart request.
  • The files is stored in the attachment list with the name specified by the filename parameter.
Click to view sample request body.
--B1pD17v6kehNbda7sT7J2JOqssMTGGvw
Content-Disposition: form-data; name="file_content_01"; filename="receipt_oct29.jpg"
Content-Type: image/jpeg
<insert base-64 encoded file content for receipt_oct29.jpg here>
--B1pD17v6kehNbda7sT7J2JOqssMTGGvw
Content-Disposition: form-data; name="file_content_02"; filename="receipt_june10.pdf"
Content-Type: application/pdf
<insert base-64 encoded file content for receipt_june10.pdf here>
--B1pD17v6kehNbda7sT7J2JOqssMTGGvw--

Response body

The image below shows the resulting QuickBooks UI representation of the attachment list and how it relates to the Attachable metadata objects returned in the response payload.

Attachments.png

An array of Attachable objects is returned in response body. Going forward, you can perform other operations on this object, as required. See Attachable in the QuickBooks Online API reference for complete details on supported operations.

Click to view sample response body.
{
  "AttachableResponse": [
    {
      "Attachable": {
        "FileName": "receipt_oct29.jpg",
        "FileAccessUri": "/v3/company/1029354210/download/100000000004062174",
        "TempDownloadUri": "https://...",
        "Size": 1594261,
        "ContentType": "image/jpeg",
        "ThumbnailFileAccessUri": "/v3/company/1029354210/attachable-thumbnail/100000000004062174",
        "domain": "QBO",
        "sparse": false,
        "Id": "100000000004062174",
        "SyncToken": "0",
        "MetaData": {
          "CreateTime": "2015-10-29T16:04:05-07:00",
          "LastUpdatedTime": "2015-10-29T16:04:05-07:00"
        }
      }
    },
    {
      "Attachable": {
        "FileName": "receipt_june10.pdf",
        "FileAccessUri": "/v3/company/1029354210/download/100000000004062175",
        "TempDownloadUri": "https://...",
        "Size": 7933,
        "ContentType": "application/pdf",
        "domain": "QBO",
        "sparse": false,
        "Id": "100000000004062175",
        "SyncToken": "0",
        "MetaData": {
          "CreateTime": "2015-10-29T16:04:06-07:00",
          "LastUpdatedTime": "2015-10-29T16:04:06-07:00"
        }
      }
    }
  ],
  "time": "2015-10-29T16:04:02.620-07:00"
}

Downloading attachments

This operation retrieves a temporary download URL to the specified attachment. This URL expires after 15 minutes. The application uses this URL to then download the file as a separate step. If this URL expires, the app may obtain another.

Operation:GEThttps://quickbooks.api.intuit.com/v3/company/<realmID>/download/attachableID
Content type:text/plain

The attachableID is the Id of the Attachable metadata object assigned during the upload operation to the attachment list. This is returned in the Attachable response body in the Id attribute.

The endpoint has the following behavior:

  • Checks that the user has permission to view the attachment.
  • Checks that user has permissions to view the entities that link to the attachment.
  • Retrieves a temporary download URL from the storage service. This URL expires in 15 minutes. The content type is plain/text with the temporary URL returned via the TempDownloadUrl attribute in the response.

Response body

https://intuit-.../attachments/receipt_june10.pdf?Expires=...&AWSAccessKeyId=...&Signature=...

Thumbnails

To retrieve a temporary download URL for the associated thumbnail, use the following endpoint:

https://quickbooks.api.intuit.com/v3/company/<realmID>/attachable-thumbnail/attachableID

The attachableID is the Id of the Attachable metadata object assigned during the upload operation to the attachment list. This is returned in the Attachable response body in the Id attribute.

Approved file types

The table below lists the approved attachment list file types. 

File typeContent type
aiapplication/postscript
csvtext/csv
docapplication/msword
docxapplication/vnd.openxmlformats-officedocument.wordprocessingml.document
epsapplication/postscript
gifimage/gif
jpegimage/jpeg
jpgimage/jpg
odsapplication/vnd.oasis.opendocument.spreadsheet
pdfapplication/pdf
pngimage/png
rtftext/rtf
tifimage/tiff
txttext/plain
xlsapplication/vnd.ms-excel
xlsxapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet
xmltext/xml

You app receives an error message similar to the one below if an attempt is made to upload a file type other than those listed above.

{
    "AttachableResponse": [
        {
            "Fault": {
                "Error": [
                    {
                        "Message": "Invalid Uploaded File",
                        "Detail": "The uploaded file is invalid. Supplied Content Type: File Content Type:application/zip, File Name: File Name:receipt_nov15.zip",
                        "code": "6041"
                    }
                ],
                "type": "ValidationFault"
            }
        }
    ],
    "time": "2017-06-15T11:56:51.711-07:00"
} 

Learn more

View the Attachable, Upload, and Download API references here.

 Got Questions? Get Answers in our developer forums.