Hi Guys,
We have a few automation systems running and wondering how I can insert an attachment to a purchase invoice or a sales invoice when saving via API. And is it base64 Encoded or binary.
Hi Guys,
We have a few automation systems running and wondering how I can insert an attachment to a purchase invoice or a sales invoice when saving via API. And is it base64 Encoded or binary.
You can’t as far as I know because I don’t think attachment files are accessible.
But I would definitely like to know.
This would definitely be a useful feature to consider as clients could attach their purchase orders for example.
Hi @bdallen, so yes it is possible to add an attachment to a Sales invoice via Automation (notice I didn’t use the “api” word)
The real issue is that once it’s added it not that easy to get it back again by simply requesting a pdf version of the invoice for example. (attachments are not added to pdf)
Some assumptions made and info required:
a. assumption is you have an Admin user setup for All access (e.g. adminusr:adminPassword)
b. You have HTTPS access to your ServerManager
c. My internal test site is: https://dev.miotest.local/ behind an nginX config.
Here is a basic overview on how you achieve it.
curl -v --user "adminusr:adminPassword" -H "Content-Type: application/octet-stream" -H "X-File-Name: MyTestFile.jpg" -H "X-File-Type: image/jpeg" --data-binary @simage.jpg "https://dev.miotest.local/new-attachment?Source=260e4d4a-d83d-444a-a86d-4d42b569b720&FileID=Tm9ydGh3aW5kQVBJ"
The response will be some JSON with the UUID of the attachment:
{"key":"362a78f3-61fa-466f-b122-612328aa27b3","view":"/view-attachment?Key=362a78f3-61fa-466f-b122-612328aa27b3&FileID=Tm9ydGh3aW5kQVBJ","delete":"/remove-attachment?Key=362a78f3-61fa-466f-b122-612328aa27b3&FileID=Tm9ydGh3aW5kQVBJ"}
To find “details” about the object, you can use the "/api/FileID/2e541a82-94d7-42fc-a388-26bdc0803455/index.json"
fixed Attachments endpoint or directly via: "/api/FileID/362a78f3-61fa-466f-b122-612328aa27b3.json"
- the object endpoint.
Thanks Mark, I shall give this a shot.
Works like a charm. Using Python.
# Upload Attachment
def UploadAttachment(self, attachment_name, attachment_data):
if '.pdf' in attachment_name:
bheaders = {'Content-Type': 'application/octet-stream', 'X-File-Name': attachment_name, 'X-File-Type': 'application/pdf'}
if '.jpg' in attachment_name:
bheaders = {'Content-Type': 'application/octet-stream', 'X-File-Name': attachment_name, 'X-File-Type': 'image/jpeg'}
else:
raise('Unknown File Type for Upload please use jpg or pdf')
payload_bytes = attachment_data.encode('ascii')
payload = base64.decodebytes(payload_bytes)
resp = requests.post(self.__application.Service_URL + '/new-attachment?Source=' + self.id + '&FileID=' + self.bus_id, data=payload, headers=bheaders, auth=(self.__application.API_Username, self.__application.API_Password))
reply = resp.status_code
if reply != 200:
raise('Error Uploading Attachment to Manager')
Thanks for the contribution Brendon!
Just for anyone that may be leaning towards php, here is a PHP version that runs using the Laravel Framework Artisan Command that can be added to the command.php routes file. (e.g. php artisan api:attach)
<?php
use GuzzleHttp\Client;
Artisan::command('api:attach {fileId : The unique ID of the Company File} {uuid : UUID for the Invoice, Quote etc that you want the attachment added to} {file : Full path to the locally hosted resource to be uploaded}', function($fileId, $uuid, $file) {
$this->info('Wait... Attempting to upload an attachment...');
// Make sure file exists...
if (!file_exists($file)) {
$this->error('Error! Unable to find the file specified ('.$file.')');
return;
}
$config = config('managerapi');
$host = $config['host'] ?? null;
$port = $config['http_port'] ?? null;
$user = $config['username'] ?? null;
$password = $config['password'] ?? null;
$hostName = $host . ($port ? ':'.$port : '');
$this->info('Using Host Name ' . $hostName);
// open the file read only
$fHandle = fopen($file, "r");
// Create Guzzle Client options
$opts = [
'auth' => [$user, $password],
'body' => $fHandle,
'headers' => [
'Content-Type' => 'application/octet-stream',
'X-File-Name' => basename($file),
'X-File-Type' => mime_content_type($file),
]];
// Create a new Client
$client = new Client();
$response = $client->request('POST',$hostName . '/new-attachment?Source='.$uuid.'&FileID='. $fileId, $opts);
// Make sure it worked ok
if (200 == $response->getStatusCode()) {
$result = json_decode((string) $response->getBody(),true);
// Output results in a table
$this->table(['Name','Data'], [['key', $result['key']],['view', $result['view']],['delete', $result['delete']]]);
return;
} else {
$this->error('Unknown error occured');
dd($response);
}
})->describe('Upload a file attachment, pdf, doc, image etc. to an Invoice, Quote and other forms');
If successful the UUID and other links are output as in…
php artisan api:attach Tm9ydGh3aW5kQVBJ "d26b982b-8a51-4218-af06-f1d5080255fe" \Images\metoo.jpg
Should produce the following results:
Wait... Attempting to upload an attachment...
Using Host Name https://xxx.xxx.local
+--------+-------------------------------------------------------------------------------------+
| Name | Data |
+--------+-------------------------------------------------------------------------------------+
| key | 83c1910b-4f83-43f4-8182-b4e5b887b621 |
| view | /view-attachment?Key=83c1910b-4f83-43f4-8182-b4e5b887b621&FileID=Tm9ydGh3aW5kQVBJ |
| delete | /remove-attachment?Key=83c1910b-4f83-43f4-8182-b4e5b887b621&FileID=Tm9ydGh3aW5kQVBJ |
+--------+-------------------------------------------------------------------------------------+