I’ve been working with Autentique GraphQL API and it is requiring the use of FormData
JS objects to deal with “multipart/form-data” requests.
Document create documentation: Autentique (scroll down to Node.js approach)
My code in Workflow:
const record = await tape.Record.get(12393083)
const file = record.data.fields.find(field => field.external_id === 'files');
const fileLink = file.values[0].value.link;
let response = await http.get(fileLink);
// Dados do arquivo em forma de buffer
const fileBuffer = Buffer.from(response.data);
const autentique_base_url = "https://api.autentique.com.br/v2/graphql";
const autentique_access_token = "token_here";
const autentique_filename = "Contrato de Teste.pdf";
const autentique_email = 'graco.silva@gentilnegocios.com.br';
const requestHeaders = {
'Authorization': `Bearer ${autentique_access_token}`, // Token de autorização
'Content-Type': "multipart/form-data", // Tipo de conteúdo da solicitação
};
const query = "mutation CreateDocumentMutation($document: DocumentInput!, $signers: [SignerInput!]!, $file: Upload!) {createDocument(document: $document, signers: $signers, file: $file) {id name refusable sortable created_at signatures { public_id name email created_at action { name } link { short_link } user { id name email }}}}";
const variables = {
"document":{
"name": autentique_filename
},
"signers":[
{
"email": autentique_email,
"action":"SIGN"
}
],
"file": fileBuffer
};
response = await http.upload(
{
url: autentique_base_url,
headers: requestHeaders,
data: {
query: query,
variables: variables,
},
},
{
url: fileLink
}
);
console.log(JSON.stringify(response));
That causes a HTTP 500 error.
Have you ever tried similar works to upload a document to sign? Can you help me with that, maybe with Tape new features?
1 Like
Here is my approach with the custom payload as parts
.
// Getting a file from a record
const record = await tape.Record.get(12393083);
const file = record.data.fields.find(field => field.external_id === 'files');
const fileValue = file.values[0] ? file.values[0].value : {};
const fileLink = fileValue ? fileValue.link : '';
const fileName = fileValue ? fileValue.name : '';
const fileContentType = fileValue ? fileValue.mimetype : 'application/octet-stream';
// Download the file
let response = await http.get(fileLink);
const fileContent = response.data;
const autentiqueBaseUrl = "https://api.autentique.com.br/v2/graphql";
const autentiqueAccessToken = "token_here";
const autentiqueEmail = 'graco.silva@gentilnegocios.com.br';
// Create a unique boundary for the multipart/form-data
const boundary = '----Autentique123';
// Construct the multipart/form-data payload
const parts = [
`--${boundary}\r\nContent-Disposition: form-data; name="operations"\r\n\r\n`,
JSON.stringify({
query: "mutation CreateDocumentMutation($document: DocumentInput!, $signers: [SignerInput!]!, $file: Upload!) {createDocument(document: $document, signers: $signers, file: $file) {id name refusable sortable created_at signatures { public_id name email created_at action { name } link { short_link } user { id name email }}}}",
variables: {
document: { name: fileName },
signers: [{ email: autentiqueEmail, action: "SIGN" }],
file: null
}
}),
`\r\n--${boundary}\r\nContent-Disposition: form-data; name="map"\r\n\r\n`,
JSON.stringify({ "file": ["variables.file"] }),
`\r\n--${boundary}\r\nContent-Disposition: form-data; name="file"; filename="${fileName}"\r\nContent-Type: ${fileContentType}\r\n\r\n`,
fileContent,
`\r\n--${boundary}--`
];
const postData = parts.join('');
// Set the headers
const headers = {
'Authorization': `Bearer ${autentiqueAccessToken}`,
'Content-Type': `multipart/form-data; boundary=${boundary}`,
// 'Content-Length': String(Buffer.byteLength(body))
};
// Send the request
http.post(autentiqueBaseUrl, {
headers: headers,
data: postData
})
.then(response => {
console.log(JSON.stringify(response));
})
.catch(error => {
console.error(error);
});
2 Likes
Sorry for the inconvenient but my previous solution had a lack.
The document was created as blank due to the payload as a string considered like a txt file.
I have to convert it to a Buffer but with http
module the API is responding wrong. It generates a HTTP 500 error.
const fileLink = remotehttpcall_field_files_file_url;
const fileName = remotehttpcall_field_files_filename;
if(!fileLink) {
console.warn('File link not found!');
}else{
// Create a unique boundary for the multipart/form-data
const boundary = '----Autentique123';
// Download the file
let {data: fileContent} = await http.get(fileLink, {responseEncoding: 'binary'});
// Autentique credentials
const autentiqueBaseUrl = "https://api.autentique.com.br/v2/graphql";
const autentiqueAccessToken = "token_here";
const autentiqueEmail = 'graco.silva@gentilnegocios.com.br';
const operations = JSON.stringify({
query: "mutation CreateDocumentMutation($document: DocumentInput!, $signers: [SignerInput!]!, $file: Upload!) {createDocument(document: $document, signers: $signers, file: $file) {id name refusable sortable created_at signatures { public_id name email created_at action { name } link { short_link } user { id name email }}}}",
variables: {
document: { name: fileName },
signers: [{ email: autentiqueEmail, action: "SIGN" }],
file: null
}
});
const mapContent = JSON.stringify({ "file": ["variables.file"] });
// Data string
let data = "";
data += `--${boundary}\r\n`;
data += 'Content-Disposition: form-data; name="operations"\r\n\r\n';
data += `${operations}\r\n`;
data += `--${boundary}\r\n`;
data += 'Content-Disposition: form-data; name="map"\r\n\r\n';
data += `${mapContent}\r\n`;
data += `--${boundary}\r\n`;
data += `Content-Disposition: form-data; name="file"; filename="${fileName}"\r\n`;
data += 'Content-Type: application/pdf\r\n\r\n';
const payload = Buffer.concat([
Buffer.from(data, 'utf8'),
Buffer.from(fileContent, 'binary'),
Buffer.from(`\r\n--${boundary}--\r\n`, 'utf8'),
]);
// Set the headers
const headers = {
'Authorization': `Bearer ${autentiqueAccessToken}`,
'Content-Type': `multipart/form-data; boundary=${boundary}`
};
// Send the request
http.post(autentiqueBaseUrl, {
headers: headers,
data: payload
})
.then(response => {
console.log(JSON.stringify(response));
})
.catch(error => {
console.error(error);
});
}
When I send the data buffer inside a “Send HTTP request” action it is processed well, but the document remains blank.
Can you help me with that, @Tim @Leo ?
Best,
Graco.
1 Like
Leo
November 13, 2023, 11:04am
4
Hi @gracosilva ,
thank you very much for your detailed description of your problem.
We have scheduled a slot today to analyze your issue in detail and to find a solution for you.
I will get back to you as soon as we have the first results.
Cheers
Leo
Ben
November 14, 2023, 1:22pm
5
Hi @gracosilva
I checked your code yesterday in detail and could not find any errors, I would have built it very similar to you. But there is most certainly a way to connect Autentique without throwing a 500 error.
But for that we have to extend our lab and make an account with Autentique ourselves to test different approaches.
Unfortunately, we don’t have the time during the week, but we’ll make time for this at the weekend and should have a solution for you by Monday at the latest.
Best,
Ben
Hi Ben. Don’t worry.
I’m only struggling with the blank content when running with a Send HTTP request
action. That is, another separate block. It didn’t generate HTTP 500 error no more.
Best,
Graco.
Ben
November 17, 2023, 1:23pm
7
Hi @gracosilva ,
great that you have already solved the HTTP 500 error.
After my tests yesterday I am very sure that the blank content is also caused by an interaction with Autentique.
That’s why we need the lab and a dedicated account with the service to understand the problem. We will take the time this weekend.
Best
Ben
Hi Ben! Great for this moment.
I’m really enjoying your effort to get the job done and help my team at Gentil Negócios.
I could share the Autentique credentials with you in DM, for instance on Microsoft Teams. What do you think?
Best,
Graco.
Tim
November 26, 2023, 11:24am
9
@gracosilva thanks for your patience - after we reproduced your use case inside our lab using an Autentique account, we figured it is hardly possible with the regular http.post
method. In order to allow using the form data spec inside of workflow automations, we added a new method postFormData
to the Workflow execution context HTTP client that handles the implementation details. With that, it is now easily possible to create the PDF documents from Tape.
We added a simple guide that concludes your use case:
Due to various community requests from Brazil , we created this guide that shows how to create a signature document inside of Autentique using their API and Tape workflow automations. We are going to use a PDF that is stored inside Tape - it could also be generated beforehand inside of Tape using the PDF action .
This enables countless use cases, e.g. creating contract documents based on your data in Tape and having them signed by your clients via Autentique …
Be sure to let us know how this works for you, and hit me up if you have questions.
Cheers & happy signing in
Tim
3 Likes