Integração com cURL
Envie um arquivo ou lote à automação do painel e receba os resultados no seu servidor.
Você vai precisar de uma automação publicada e uma chave com execute e read.
Nesta página
Configure os dados do painel
Copie a chave autorizada, o ID e a versão publicada da automação. Configure as quatro variáveis no ambiente do servidor.
# Bash, cURL 7.76+, jq e OpenSSLexport DUCKFILE_API_URL=https://duckfile.com/api/v1/externalexport DUCKFILE_API_KEY=SUA_CHAVE_NO_SERVIDORexport DUCKFILE_AUTOMATION_ID=UUID_DA_AUTOMACAOexport DUCKFILE_AUTOMATION_VERSION=1Use HTTPS com certificado válido e mantenha a chave somente no backend.
Envie e receba os arquivos
Baixe o arquivo de integração, incorpore ao seu projeto e chame a função. Ela envia, acompanha e recebe cada resultado individualmente. Aceita um caminho ou uma lista de caminhos.
# Após configurar as quatro variáveis de ambiente:bash duckfile.sh imagem.pngGuarde os arquivos recebidos no seu próprio sistema. A execução não salva nada na biblioteca da conta.
Use os resultados no seu negócio

A função retorna o ID, o estado e os caminhos locais em arquivos. Em resultado parcial, preserve os itens recebidos e trate as falhas separadamente. A função só termina após baixar os resultados disponíveis.
{"id":"UUID_DA_EXECUCAO","status":"COMPLETED","arquivos":[{"id":"UUID_DO_ARQUIVO","path":"resultado-UUID.webp","bytes":12345}],"falhas":[]}Código da integração

Fonte de exemplo, sem SDK oficial. Você pode incorporar e adaptar a implementação, incluindo persistir a chave de idempotência e o ID da execução para recuperar falhas de rede. Nenhuma etapa da automação é definida nesse código.
#!/usr/bin/env bashset -euo pipefailbase=${DUCKFILE_API_URL%/}key=${DUCKFILE_API_KEY:?Configure a chave no servidor.}automation=${DUCKFILE_AUTOMATION_ID:?Copie o ID no painel.}version=${DUCKFILE_AUTOMATION_VERSION:?Copie a versão publicada.}[[ $base =~ ^https://[^/@?#]+/api/v1/external$ ]] || { echo 'Configure a base HTTPS da API.' >&2; exit 1; }uuid='^[a-fA-F0-9]{8}-([a-fA-F0-9]{4}-){3}[a-fA-F0-9]{12}$'[[ $automation =~ $uuid && $version =~ ^[1-9][0-9]*$ && $key != *$'\n'* && $key != *$'\r'* ]] || exit 1(( $# > 0 && $# <= 100 )) || { echo 'Informe um arquivo ou lote.' >&2; exit 1; }request_id=${DUCKFILE_REQUEST_ID:-$(openssl rand -hex 16)}work_dir=$(mktemp -d './.duckfile-XXXXXX')trap 'exit_status=$?; if (( exit_status != 0 )); then printf "Idempotency-Key para repetir: %s\n" "$request_id" >&2; fi; rm -rf "$work_dir"' EXITprintf 'Authorization: Bearer %s\n' "$key" > "$work_dir/headers"chmod 600 "$work_dir/headers"parts=(--form "version=$version")index=0; total=0for path in "$@"; do suffix=$(printf '%s' "${path##*.}" | tr '[:upper:]' '[:lower:]') case $suffix in png) mime=image/png;; jpg|jpeg) mime=image/jpeg;; webp) mime=image/webp;; avif) mime=image/avif;; *) exit 1;; esac size=$(wc -c < "$path" | tr -d ' ') total=$((total + size)) (( size > 0 && size <= 25000000 && total <= 79000000 )) || { echo 'Respeite 25 MB/arquivo e 80 MB com o formulário.' >&2; exit 1; } index=$((index + 1)) # Um nome temporário seguro evita interpretar caracteres do caminho como opções multipart. cp -- "$path" "$work_dir/input-$index.$suffix" parts+=(--form "files=@$work_dir/input-$index.$suffix;type=$mime")donerequest() { local route=$1; shift curl --disable --proto '=https' --proto-redir '=https' --location --max-redirs 0 \ --silent --show-error --fail-with-body --connect-timeout 10 --max-time 150 \ --header "@$work_dir/headers" "$base$route" "$@"}request "/automations/$automation/runs" --header "Idempotency-Key: $request_id" "${parts[@]}" > "$work_dir/run.json"run_id=$(jq -er '.data.id' "$work_dir/run.json")[[ $run_id =~ $uuid ]] || exit 1deadline=$((SECONDS + 35*60))while :; do status=$(jq -er '.data.status' "$work_dir/run.json") case $status in COMPLETED|PARTIAL|FAILED|CANCELLED|EXPIRED) break;; esac (( SECONDS < deadline )) || { echo "Acompanhe a execução $run_id antes de reenviar." >&2; exit 1; } sleep 2 request "/runs/$run_id" > "$work_dir/run.json"doneprintf '[]' > "$work_dir/files.json"while IFS= read -r item; do file_id=$(jq -er '.id' <<< "$item") route=$(jq -er '.result.path' <<< "$item") expected=$(jq -er '.result.bytes' <<< "$item") [[ $file_id =~ $uuid && $route == "/runs/$run_id/files/$file_id" && $expected =~ ^[0-9]+$ ]] || exit 1 (( expected > 0 && expected <= 100000000 )) || exit 1 mime=$(jq -er '.result.mimeType' <<< "$item") case $mime in image/png) suffix=png;; image/jpeg) suffix=jpg;; image/webp) suffix=webp;; image/avif) suffix=avif;; *) exit 1;; esac target="resultado-$file_id.$suffix" request "$route" --max-filesize "$expected" --output "$work_dir/output" actual=$(wc -c < "$work_dir/output" | tr -d ' ') (( actual == expected )) || { echo 'Arquivo recebido incompleto.' >&2; exit 1; } ln -- "$work_dir/output" "$target" rm -- "$work_dir/output" jq --arg id "$file_id" --arg path "$target" --argjson bytes "$actual" '. + [{id:$id,path:$path,bytes:$bytes}]' "$work_dir/files.json" > "$work_dir/files.next" mv "$work_dir/files.next" "$work_dir/files.json"done < <(jq -c '.data.files[] | select(.result != null)' "$work_dir/run.json")(( $(jq 'length' "$work_dir/files.json") > 0 )) || { echo "Nenhum arquivo disponível: $status" >&2; exit 1; }jq --slurpfile arquivos "$work_dir/files.json" '.data | {id,status,arquivos:$arquivos[0],falhas:[.files[] | select(.status != "COMPLETED" or .partial)]}' "$work_dir/run.json"Trate falhas e reenvios

Não crie outra execução apenas porque a conexão caiu. Preserve a chave de idempotência e os mesmos arquivos. Acompanhe o ID já recebido; mudança de versão, falta de crédito e falha de validação exigem tratamento próprio.