After obtaining an invoice ID from /invoices/invoice
, use /invoices/document
to find the
relevant document(s):
/invoices/document?q[linked_to.invoice_id]=invoice:abcdef
You'll find a list of documents pertaining to the invoice. Locate the document you wish to download. In the result set
you'll find a download_url
property. Please note that this URL requires a valid web session on the
Simplicate application. To programmatically download the documents, please continue.
From the result of /invoices/document
, use the id
(as document:abcdef
), to proceed to:
/documents/download/document:abcdef
This is the location of the actual document. If the document is a PDF, the API will respond with a Content-Type:
application/pdf
header. In all other
cases, the API will respond with Content-Type: application/octet-stream
header.
Please note: the /invoices/document
and /documents/download
API's are
protected by all the relevant rights in the Simplicate application. When trying to download documents, please make sure
you're using the API keys of a user who has access to these documents.
Uploading files⁋
When uploading documents to Simplicate, you'll follow this flow:
- Let the API know your intentions; what's the file name, of what file size
- Upload the file (repeatedly if need be), in chunks of max
500 kB
.
- The API will let you know you've uploaded all you needed, and that the file is complete
- You'll be able to create a document, and link to this file, or use it as an attachment in timeline messages
Start by letting the API know you're about to submit a file. For this example, we'll upload this image:
. Send the following body to
/upload/chunked
.
POST /api/v2/upload/chunked
{
"file_name": "simplicate-logo.png",
"file_size": 858
}
Note that file size is in bytes. The result will be like:
200 OK
{
"data": {
"chunked_upload_id": "chunkedupload:a00a5662be4cf8b54da2058e5c846d06"
}
}
We're going to use this ID to start uploading the actual contents of the file. Please note that the file contents must be base64
encoded, and each chunk must not exceed 500 kB (base64 encoded).
PUT /api/v2/upload/chunked/chunkedupload:a00a5662be4cf8b54da2058e5c846d06
{
"chunk": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAACxKAAAsSgF3enRNAAADDElEQVRIiY1VO2hUQRTd7LoRjYpg/EOipEgRxUJRDNgoVhZKUAu/BH8E0lgoNjbpFNGAhZ95hQTnqYU2In6QFBoEg2gjFiYiJiKopHCeEgWT9dyZM7uzEXb2weG+N2/u78y9d3K54EmTLKcTIzKvlZXL0sSchRwCJoAS8BN4g/+XIdeldp8RvQbRr/nQeIPGRsjDUPymnVGPXzA8jfVSquz3FHAO79aJ6NZ2oEyeG89oGMC3GBnB2inILcBaYCPQ7bIydGzuAo2iG3MgkXQFEQ8A81KX0QzYQPrECbM8XwdFWRM2jdL4nSqDyiyCsTVAi1CJYMTxI+79iLWOqAPHu1X4Dqxwhm20vaDsM//9wFo/5CAjH4PxNjlsoTiWwX3yeo0UCA4GlJlUmfDQx+C4HRDjBR07Ayh8peIxW7IKpafMMJ3eAJbivYd7xvF/JYPISwXVQ9EfKu/lQc6B9NRspVPZtxNyNeRy4AIw2wcUczBOCnpdA9noBl0G5jEoKGq/7uRr7frhnj0rFc3ApDZalaUuIutge8D5Q8s1uxffR+Foik13qR6KdrFLJ/He4SqIB63K3fsAe2aVx4oyJ4MANtR0wFExzM3PoVwMnBwIM8F6YzWNmTTcrVgGknonKPhLQ09tJysXMXCo7ERl1xmQlHc3K22ytgPwS0N7GBGGnVnINf4zJzgeZPCtohN0eDYtFNaRga1pcbYjdXUupdgPg/PZ2XPFODPZTJ0WwGYdy4CjAfw6xWYYe8/0pUw7gavOuJH7YTGzWu+pqyeDAp20wtiorkzLkh/PdpQn2Wntp6qtJNsrE5EMcJM5J0LNiHZKL4Dd+H4C+QHyFXBcVyatZPuWGVys6YBKbam9ZKzCEA6yKRgRS7CnmFbfCVdSP2UT0xpxIHdrto0VZB0A7SzFmZdNM+SA5x4B9NTRyeUrs8tXBfAbHN+EPCJDDtgnVQU6vwSN18fxEbmTwzJNsk3Ay8CIHxUlNxBldJhP+N4fUBjJoNL6Ba8EyGhOgGdYe0ent+2gS7IFzNgH9Z/NfzoINxdnkeUkAAAAAElFTkSuQmCC"
}
As this file is way smaller than 500 kB, the API will set the state to 'done', and no new chunks will be accepted:
200 OK
{
"data": {
"pointer": 1,
"state": "done",
"upload_queue_id": "uploadqueue:7de64ec93190dd457a9bfc4dc6429b75",
"file_size_current": 858,
"file_size_expected": 858,
"download_url": "/download?name=simplicate-logo.png"
},
"errors": null,
"debug": null
}
If you're uploading a larger file, the API will respond like below, and you'll need to send the remaining chunks, until the file is
completely uploaded:
200 OK
{
"data": {
"pointer": 1,
"state": "in_progress",
"file_size_current": 384000,
"file_size_expected": 3781286
},
"errors": null,
"debug": null
}
Converting to document⁋
With the upload_queue_id
in hand, we can convert this file to a document, with a title, a
document type id
, and link it to an existing entity
(Person, Organization, Sales, Project, Invoice)
POST /api/v2/documents/document
{
"upload_queue_id": "uploadqueue:7de64ec93190dd457a9bfc4dc6429b75",
"title": "simplicate-logo.png",
"document_type_id": "documenttype:b423eae1f54f879041c55b3092b4a1f8",
"linked_to": {
"person_id": "person:b1c692b0993bb602eb694ed52cdf49ac"
}
}
---
200 OK
{
"data": {
"id": "document:91b5a2aee0d60fae298fdc63dd8ada0b"
}
}
This file can now be found in its linked entity, on the tab 'Documents'.
As a timeline message attachment⁋
Additionally, if you wish to link this document to a timeline message, then please see
POST /timeline/attachment
, and send the following request:
POST /api/v2/timeline/attachment
{
"message_id": "message:914edc4509a28e23ccd1f796716510b1",
"document_id": "document:91b5a2aee0d60fae298fdc63dd8ada0b"
}
That's it for uploading files, and using them as documents!
PHP example for uploading chunks⁋
A PHP example for uploading a file, in chunks:
function uploadFileToApi(string $fileName, string $filePath): string
{
$uploadId = $this->callSimplicate('POST', '/upload/chunked', [
'file_name' => $fileName,
'file_size' => filesize($filePath),
]);
$chunkSize = 500 * 1000; // 500 kB, times a thousand, for bytes, to err on the side of caution
$base64String = base64_encode(file_get_contents($filePath));
$offset = 0;
while (true) {
$chunk = substr($base64String, $offset, $chunkSize);
$offset += $chunkSize;
$apiResponse = $this->callSimplicate('PUT', '/upload/chunked/' . $uploadId, [
'chunk' => $chunk,
]);
if (!isset($apiResponse['data']) || !isset($apiResponse['data']['state'])) {
throw new Exception('Expected a succesful API resonse, with data and data.state');
}
if ($apiResponse['data']['state'] === 'done') {
return $apiResponse['data']['upload_queue_id'];
}
}
}
$uploadQueueId = uploadFileToApi('simplicate-logo.png', '/path/to/simplicate-logo-24x24px.png');