1
Peça a URL assinada
GET /file/signature devolve a URL de upload e o identificador do arquivo.2
Envie o arquivo
PUT na URL assinada, com o conteúdo binário. Esta requisição vai para o storage, não para a API do Hust, e não leva o seu token.3
Envie a mensagem
POST /message/send com o uuid e o filePath recebidos no primeiro passo.1. Obter a URL assinada
GET https://api.hustapp.com/file/signature
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
fileName | string | Sim | Nome original do arquivo, com extensão. A extensão determina como o Hust classifica a mídia. |
contentType | string | Sim | Tipo MIME do arquivo. Por exemplo: image/png, application/pdf. |
tempFile | boolean | Não — padrão true | Quando true, o arquivo vai para um diretório temporário com TTL de 48 horas. |
curl -G https://api.hustapp.com/file/signature \
-H "Authorization: Bearer SEU_TOKEN" \
--data-urlencode "fileName=comprovante.pdf" \
--data-urlencode "contentType=application/pdf" \
--data-urlencode "tempFile=true"
const params = new URLSearchParams({
fileName: "comprovante.pdf",
contentType: "application/pdf",
tempFile: "true",
});
const res = await fetch(`https://api.hustapp.com/file/signature?${params}`, {
headers: { Authorization: `Bearer ${token}` },
});
const { signedUrl, uuid, filePath } = await res.json();
import requests
res = requests.get(
"https://api.hustapp.com/file/signature",
headers={"Authorization": f"Bearer {token}"},
params={"fileName": "comprovante.pdf", "contentType": "application/pdf", "tempFile": "true"},
)
signature = res.json()
<?php
$query = http_build_query([
'fileName' => 'comprovante.pdf',
'contentType' => 'application/pdf',
'tempFile' => 'true',
]);
$ch = curl_init("https://api.hustapp.com/file/signature?{$query}");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$response = curl_exec($ch);
curl_close($ch);
$signature = json_decode($response, true);
uses
System.Net.HttpClient, System.Net.URLClient, System.JSON;
var
HttpClient: THTTPClient;
Response: IHTTPResponse;
ResponseJson: TJSONObject;
SignedUrl, FileUuid, FilePath: string;
begin
HttpClient := THTTPClient.Create;
try
HttpClient.CustomHeaders['Authorization'] := 'Bearer ' + Token;
Response := HttpClient.Get(
'https://api.hustapp.com/file/signature?fileName=comprovante.pdf' +
'&contentType=application/pdf&tempFile=true');
ResponseJson := TJSONObject.ParseJSONValue(Response.ContentAsString) as TJSONObject;
try
SignedUrl := ResponseJson.GetValue<string>('signedUrl');
FileUuid := ResponseJson.GetValue<string>('uuid');
FilePath := ResponseJson.GetValue<string>('filePath');
finally
ResponseJson.Free;
end;
finally
HttpClient.Free;
end;
end;
| Campo da resposta | Tipo | Descrição |
|---|---|---|
signedUrl | string | URL para onde você envia o arquivo. Tem validade curta. |
uuid | string | Identificador do arquivo no Hust. É o que você informa no envio da mensagem. |
filePath | string | Caminho do arquivo no storage. |
Com
tempFile: true, o arquivo é apagado 48 horas depois do upload. Se a sua integração agenda envios ou guarda uuid para reutilizar depois, esse prazo precisa entrar na conta.2. Enviar o arquivo
Faça umPUT na signedUrl com o conteúdo binário. Os dois cabeçalhos abaixo são obrigatórios, e o Content-Type precisa ser exatamente o mesmo que você informou no passo anterior.
curl -X PUT "<signedUrl>" \
-H "Content-Type: application/pdf" \
-H "Content-Disposition: attachment; filename=comprovante.pdf" \
--upload-file ./comprovante.pdf
await fetch(signedUrl, {
method: "PUT",
headers: {
"Content-Type": contentType,
"Content-Disposition": `attachment; filename=${encodeURI(fileName)}`,
},
body: fileBuffer,
});
with open("comprovante.pdf", "rb") as f:
requests.put(
signed_url,
data=f,
headers={
"Content-Type": "application/pdf",
"Content-Disposition": "attachment; filename=comprovante.pdf",
},
)
<?php
$ch = curl_init($signedUrl);
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_UPLOAD => true,
CURLOPT_INFILE => fopen('comprovante.pdf', 'r'),
CURLOPT_INFILESIZE => filesize('comprovante.pdf'),
CURLOPT_HTTPHEADER => [
'Content-Type: application/pdf',
'Content-Disposition: attachment; filename=comprovante.pdf',
],
]);
curl_exec($ch);
curl_close($ch);
uses
System.Net.HttpClient, System.Classes;
var
HttpClient: THTTPClient;
FileStream: TFileStream;
begin
HttpClient := THTTPClient.Create;
try
FileStream := TFileStream.Create('comprovante.pdf', fmOpenRead);
try
HttpClient.ContentType := 'application/pdf';
HttpClient.CustomHeaders['Content-Disposition'] :=
'attachment; filename=comprovante.pdf';
HttpClient.Put(SignedUrl, FileStream);
finally
FileStream.Free;
end;
finally
HttpClient.Free;
end;
end;
Content-Disposition deve ir codificado para URL, para suportar acentos e espaços.
Esta requisição não leva o cabeçalho
Authorization. A autorização já está embutida na assinatura da URL.3. Enviar a mensagem
Use a mesma rota do envio de texto, trocandotype pelo tipo da mídia e incluindo o objeto file. Os demais campos seguem as regras de Enviar mensagem: connection e contact obrigatórios, e department obrigatório salvo quando called é "without" ou traz um id.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
type | string | Sim | image, audio, video ou document. O Hust não deduz o tipo a partir do arquivo neste fluxo. |
file.uuid | string | Sim | O uuid recebido no passo 1. |
file.filePath | string | Ao usar arquivo temporário | O filePath recebido no passo 1. |
file.forceFile | boolean | Não — padrão false | Força a entrega como anexo, em vez do WhatsApp renderizar a mídia embutida. |
caption | string | Não | Legenda da mídia. Sofre a mesma assinatura automática do texto. |
Exemplo
{
"type": "document",
"caption": "Segue o comprovante do seu pedido.",
"file": {
"uuid": "1f8c2b7e-4a55-4f2b-9c31-0d7e5a9b2c44",
"filePath": "temp/1f8c2b7e-4a55-4f2b-9c31-0d7e5a9b2c44.pdf"
},
"connection": { "uuid": "9db04f68-9e7d-4297-ba41-5f4d4c44779a" },
"contact": { "phone": "5541988887777" },
"department": { "id": 169070 }
}
O envio não verifica se o upload do passo 2 foi concluído. Se você informar um
uuid cujo arquivo nunca chegou ao storage, a rota responde 200 e a falha só aparece depois, no processamento da fila. Confirme que o PUT retornou sucesso antes de chamar o envio.Fluxo completo
Os três passos encadeados, do pedido da assinatura até a mensagem enviada:// 1. Pede a URL assinada
const params = new URLSearchParams({
fileName: "comprovante.pdf",
contentType: "application/pdf",
tempFile: "true",
});
const signatureRes = await fetch(`https://api.hustapp.com/file/signature?${params}`, {
headers: { Authorization: `Bearer ${token}` },
});
const { signedUrl, uuid, filePath } = await signatureRes.json();
// 2. Envia o arquivo para o storage
await fetch(signedUrl, {
method: "PUT",
headers: {
"Content-Type": "application/pdf",
"Content-Disposition": "attachment; filename=comprovante.pdf",
},
body: fileBuffer, // Buffer ou Blob do arquivo lido em disco
});
// 3. Envia a mensagem referenciando o arquivo
const messageRes = await fetch("https://api.hustapp.com/message/send", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
type: "document",
caption: "Segue o comprovante do seu pedido.",
file: { uuid, filePath },
connection: { uuid: "9db04f68-9e7d-4297-ba41-5f4d4c44779a" },
contact: { phone: "5541988887777" },
called: "without",
}),
});
const message = await messageRes.json();
import requests
# 1. Pede a URL assinada
signature_res = requests.get(
"https://api.hustapp.com/file/signature",
headers={"Authorization": f"Bearer {token}"},
params={
"fileName": "comprovante.pdf",
"contentType": "application/pdf",
"tempFile": "true",
},
)
signature = signature_res.json()
signed_url, uuid, file_path = signature["signedUrl"], signature["uuid"], signature["filePath"]
# 2. Envia o arquivo para o storage
with open("comprovante.pdf", "rb") as f:
requests.put(
signed_url,
data=f,
headers={
"Content-Type": "application/pdf",
"Content-Disposition": "attachment; filename=comprovante.pdf",
},
)
# 3. Envia a mensagem referenciando o arquivo
message_res = requests.post(
"https://api.hustapp.com/message/send",
headers={"Authorization": f"Bearer {token}"},
json={
"type": "document",
"caption": "Segue o comprovante do seu pedido.",
"file": {"uuid": uuid, "filePath": file_path},
"connection": {"uuid": "9db04f68-9e7d-4297-ba41-5f4d4c44779a"},
"contact": {"phone": "5541988887777"},
"called": "without",
},
)
message = message_res.json()
<?php
// 1. Pede a URL assinada
$query = http_build_query([
'fileName' => 'comprovante.pdf',
'contentType' => 'application/pdf',
'tempFile' => 'true',
]);
$ch = curl_init("https://api.hustapp.com/file/signature?{$query}");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],
]);
$signature = json_decode(curl_exec($ch), true);
curl_close($ch);
['signedUrl' => $signedUrl, 'uuid' => $uuid, 'filePath' => $filePath] = $signature;
// 2. Envia o arquivo para o storage
$ch = curl_init($signedUrl);
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_UPLOAD => true,
CURLOPT_INFILE => fopen('comprovante.pdf', 'r'),
CURLOPT_INFILESIZE => filesize('comprovante.pdf'),
CURLOPT_HTTPHEADER => [
'Content-Type: application/pdf',
'Content-Disposition: attachment; filename=comprovante.pdf',
],
]);
curl_exec($ch);
curl_close($ch);
// 3. Envia a mensagem referenciando o arquivo
$ch = curl_init('https://api.hustapp.com/message/send');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $token,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'type' => 'document',
'caption' => 'Segue o comprovante do seu pedido.',
'file' => ['uuid' => $uuid, 'filePath' => $filePath],
'connection' => ['uuid' => '9db04f68-9e7d-4297-ba41-5f4d4c44779a'],
'contact' => ['phone' => '5541988887777'],
'called' => 'without',
]),
]);
$response = curl_exec($ch);
curl_close($ch);
$message = json_decode($response, true);
uses
System.Net.HttpClient, System.JSON, System.Classes;
var
HttpClient: THTTPClient;
Response: IHTTPResponse;
SignatureJson, RequestBody, Connection, Contact, FileObj: TJSONObject;
SignedUrl, FileUuid, FilePath: string;
FileStream: TFileStream;
begin
HttpClient := THTTPClient.Create;
try
// 1. Pede a URL assinada
HttpClient.CustomHeaders['Authorization'] := 'Bearer ' + Token;
Response := HttpClient.Get(
'https://api.hustapp.com/file/signature?fileName=comprovante.pdf' +
'&contentType=application/pdf&tempFile=true');
SignatureJson := TJSONObject.ParseJSONValue(Response.ContentAsString) as TJSONObject;
try
SignedUrl := SignatureJson.GetValue<string>('signedUrl');
FileUuid := SignatureJson.GetValue<string>('uuid');
FilePath := SignatureJson.GetValue<string>('filePath');
finally
SignatureJson.Free;
end;
// 2. Envia o arquivo para o storage
HttpClient.CustomHeaders['Authorization'] := '';
FileStream := TFileStream.Create('comprovante.pdf', fmOpenRead);
try
HttpClient.ContentType := 'application/pdf';
HttpClient.CustomHeaders['Content-Disposition'] :=
'attachment; filename=comprovante.pdf';
HttpClient.Put(SignedUrl, FileStream);
finally
FileStream.Free;
end;
// 3. Envia a mensagem referenciando o arquivo
RequestBody := TJSONObject.Create;
try
Connection := TJSONObject.Create.AddPair('uuid', '9db04f68-9e7d-4297-ba41-5f4d4c44779a');
Contact := TJSONObject.Create.AddPair('phone', '5541988887777');
FileObj := TJSONObject.Create
.AddPair('uuid', FileUuid)
.AddPair('filePath', FilePath);
RequestBody.AddPair('type', 'document');
RequestBody.AddPair('caption', 'Segue o comprovante do seu pedido.');
RequestBody.AddPair('file', FileObj);
RequestBody.AddPair('connection', Connection);
RequestBody.AddPair('contact', Contact);
RequestBody.AddPair('called', 'without');
HttpClient.CustomHeaders['Authorization'] := 'Bearer ' + Token;
HttpClient.ContentType := 'application/json';
Response := HttpClient.Post('https://api.hustapp.com/message/send',
TStringStream.Create(RequestBody.ToJSON, TEncoding.UTF8));
finally
RequestBody.Free;
end;
finally
HttpClient.Free;
end;
end;
Neste exemplo o envio usa
called: "without", então não precisa de department. Se quiser abrir atendimento, troque por department: { id: ... } — veja Modos de envio.
