Obter Arquivo de Remessa
Obter Arquivo de Remessa
Seção intitulada “Obter Arquivo de Remessa”Recupera um arquivo de remessa já gerado anteriormente através do seu token. Útil para casos em que o arquivo foi criado com sucesso pela API mas não foi recebido pelo cliente devido a falhas de rede, timeout ou interrupção de conexão.
O Que Faz
Seção intitulada “O Que Faz”Este endpoint:
- Recupera o conteúdo de um arquivo de remessa já gerado
- Retorna o mesmo conteúdo que foi retornado na criação original
- Permite reprocessar o envio ao banco em caso de falhas
Quando Usar
Seção intitulada “Quando Usar”Cenários Recomendados
Seção intitulada “Cenários Recomendados”| Cenário | Descrição |
|---|---|
| Falha de rede | A remessa foi criada (201), mas o download não completou por timeout ou queda de conexão |
| Arquivo corrompido | O arquivo foi baixado mas ficou corrompido durante a transferência |
| Reprocessamento | Necessidade de obter o arquivo novamente para reenvio ao banco |
| Auditoria | Consultar o conteúdo de uma remessa enviada anteriormente |
| Backup | Manter cópia do arquivo para fins de controle interno |
Pré-requisitos
Seção intitulada “Pré-requisitos”- Possuir o token do arquivo (retornado no header
X-BoletoCloud-Tokenda criação) - Estar em um plano personalizado
- Ter gerado a remessa usando sua API Key
Posição no Ciclo de Vida
Seção intitulada “Posição no Ciclo de Vida” ┌──────────────────┐ │ Criar Remessa │ POST /arquivos/cnab/remessas │ (201 Created) │ └────────┬─────────┘ │ ▼ ┌──────────────────┐ │ Falha de rede │ Conexão interrompida │ ou timeout │ └────────┬─────────┘ │ ▼ ┌──────────────────┐ │ ★ OBTER REMESSA │ ◄── VOCÊ ESTÁ AQUI │ GET │ └────────┬─────────┘ │ ▼ ┌──────────────────┐ │ Enviar arquivo │ Internet Banking │ ao banco │ ou VAN └──────────────────┘Fluxo de Requisição
Seção intitulada “Fluxo de Requisição”Endpoint
Seção intitulada “Endpoint”GET https://sandbox.boletocloud.com/api/v1/arquivos/cnab/remessas/{token}Produção:
GET https://app.boletocloud.com/api/v1/arquivos/cnab/remessas/{token}Parâmetros de Path
Seção intitulada “Parâmetros de Path”| Parâmetro | Tipo | Obrigatório | Tamanho | Descrição |
|---|---|---|---|---|
token | string | Sim | Variável | Token do arquivo retornado no header X-BoletoCloud-Token da criação |
Headers da Requisição
Seção intitulada “Headers da Requisição”| Header | Valor | Obrigatório | Descrição |
|---|---|---|---|
Authorization | Basic {credenciais} | Sim | Autenticação HTTP Basic com API Key |
Validações
Seção intitulada “Validações”| Validação | Regra | Código | Mensagem |
|---|---|---|---|
| Token obrigatório | Token deve ser informado no path | 400 | Token do arquivo é obrigatório |
| Token válido | Token deve corresponder a um arquivo existente | 404 | Arquivo não encontrado |
| Permissão | API Key deve ter acesso ao arquivo | 401 | Não autorizado |
| Plano | Conta deve estar no plano personalizado | 403 | Recurso não disponível para seu plano |
Respostas
Seção intitulada “Respostas”Sucesso: 200 OK
Seção intitulada “Sucesso: 200 OK”Indica que o arquivo foi encontrado e retornado com sucesso.
Headers de Resposta
Seção intitulada “Headers de Resposta”| Header | Exemplo | Descrição |
|---|---|---|
Content-Type | text/plain; charset=utf-8 | Tipo do conteúdo retornado |
Content-Disposition | inline; filename=CB070402.REM | Nome original do arquivo |
X-BoletoCloud-Version | 1.x.x | Versão da plataforma |
Corpo da Resposta
Seção intitulada “Corpo da Resposta”O corpo contém o conteúdo do arquivo CNAB em formato texto plano, idêntico ao retornado na criação.
02RETORNO01COBRANCA 00000000000012345001EMPRESA XYZ...| Código | Status | Causa | Solução |
|---|---|---|---|
400 | Bad Request | Token do arquivo ausente | Informe o token no path da URL |
401 | Unauthorized | API Key inválida ou ausente | Verifique as credenciais de autenticação |
403 | Forbidden | Plano não permite este recurso | Contate o suporte para upgrade de plano |
404 | Not Found | Arquivo não encontrado | Verifique se o token está correto |
500 | Internal Server Error | Erro interno do servidor | Tente novamente ou contate o suporte |
Exemplo de Erro
Seção intitulada “Exemplo de Erro”{ "erro": { "status": 404, "mensagem": "Arquivo de remessa não encontrado" }}Como Obter o Token
Seção intitulada “Como Obter o Token”O token do arquivo é retornado no header X-BoletoCloud-Token quando a remessa é criada:
HTTP/1.1 201 CreatedX-BoletoCloud-Token: EX-abc123def456Location: /api/v1/arquivos/cnab/remessas/EX-abc123def456Content-Disposition: inline; filename=CB070402.REMSe você não guardou o token, pode usar o endpoint Listar Remessas para descobrir os tokens das remessas disponíveis por data.
Exemplos de Código
Seção intitulada “Exemplos de Código”curl "https://sandbox.boletocloud.com/api/v1/arquivos/cnab/remessas/EX-abc123def456" \ -u "api-key_SUA-API-KEY:token" \ -o remessa.rem \ -vO arquivo será salvo como remessa.rem. O nome original está no header Content-Disposition.
import javax.ws.rs.client.ClientBuilder;import javax.ws.rs.core.Response;import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;import java.io.InputStream;import java.nio.file.Files;import java.nio.file.Paths;import static javax.ws.rs.core.MediaType.WILDCARD;import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
public class ObterRemessa { public static void main(String[] args) throws Exception { String tokenArquivo = "EX-abc123def456";
Response response = ClientBuilder.newClient() .target("https://sandbox.boletocloud.com/api/v1/arquivos/cnab/remessas") .path("/" + tokenArquivo) .register(HttpAuthenticationFeature.basic( "api-key_SUA-API-KEY", "token" )) .request(WILDCARD) .get();
System.out.println("HTTP Status: " + response.getStatus());
if (response.getStatus() == 200) { String contentDisposition = response.getHeaderString("Content-Disposition"); String fileName = contentDisposition.replaceAll(".*filename=", "").trim();
Files.copy( response.readEntity(InputStream.class), Paths.get(fileName), REPLACE_EXISTING ); System.out.println("Arquivo recuperado: " + fileName);
} else { System.err.println("Erro: " + response.readEntity(String.class)); } }}import okhttp3.*import java.io.File
fun main() { val tokenArquivo = "EX-abc123def456" val client = OkHttpClient() val credential = Credentials.basic("api-key_SUA-API-KEY", "token")
val request = Request.Builder() .url("https://sandbox.boletocloud.com/api/v1/arquivos/cnab/remessas/$tokenArquivo") .header("Authorization", credential) .get() .build()
client.newCall(request).execute().use { response -> when (response.code) { 200 -> { val fileName = response.header("Content-Disposition") ?.replace(".*filename=".toRegex(), "")?.trim() ?: "remessa.rem" File(fileName).writeBytes(response.body!!.bytes()) println("Arquivo recuperado: $fileName") } else -> println("Erro: " + response.code + " - " + response.body?.string()) } }}using System;using System.IO;using System.Net.Http;using System.Net.Http.Headers;using System.Text;using System.Threading.Tasks;
class Program{ static async Task Main(string[] args) { var tokenArquivo = "EX-abc123def456";
using var client = new HttpClient(); var credentials = Convert.ToBase64String( Encoding.ASCII.GetBytes("api-key_SUA-API-KEY:token")); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
var response = await client.GetAsync( "https://sandbox.boletocloud.com/api/v1/arquivos/cnab/remessas/" + tokenArquivo);
if ((int)response.StatusCode == 200) { var fileName = response.Content.Headers.ContentDisposition?.FileName ?? "remessa.rem"; var bytes = await response.Content.ReadAsByteArrayAsync(); await File.WriteAllBytesAsync(fileName, bytes); Console.WriteLine("Arquivo recuperado: " + fileName); } else { var body = await response.Content.ReadAsStringAsync(); Console.WriteLine("Erro: " + (int)response.StatusCode + " - " + body); } }}const https = require('https');const fs = require('fs');
const tokenArquivo = 'EX-abc123def456';
const options = { hostname: 'sandbox.boletocloud.com', path: '/api/v1/arquivos/cnab/remessas/' + tokenArquivo, method: 'GET', auth: 'api-key_SUA-API-KEY:token'};
const req = https.request(options, (res) => { if (res.statusCode === 200) { const match = (res.headers['content-disposition'] || '') .match(/filename=(.+)/); const fileName = match ? match[1].trim() : 'remessa.rem';
const file = fs.createWriteStream(fileName); res.pipe(file); file.on('finish', () => { console.log('Arquivo recuperado: ' + fileName); }); } else { let body = ''; res.on('data', chunk => body += chunk); res.on('end', () => console.log('Erro: ' + res.statusCode + ' - ' + body)); }});
req.end();package main
import ( "fmt" "io" "net/http" "os" "regexp" "strings")
func main() { tokenArquivo := "EX-abc123def456" url := "https://sandbox.boletocloud.com/api/v1/arquivos/cnab/remessas/" + tokenArquivo
req, _ := http.NewRequest("GET", url, nil) req.SetBasicAuth("api-key_SUA-API-KEY", "token")
resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close()
if resp.StatusCode == 200 { re := regexp.MustCompile("filename=(.+)") match := re.FindStringSubmatch( resp.Header.Get("Content-Disposition")) fileName := "remessa.rem" if len(match) > 1 { fileName = strings.TrimSpace(match[1]) }
file, _ := os.Create(fileName) defer file.Close() io.Copy(file, resp.Body) fmt.Println("Arquivo recuperado:", fileName) } else { body, _ := io.ReadAll(resp.Body) fmt.Printf("Erro: %d - %s\n", resp.StatusCode, string(body)) }}<?php$tokenArquivo = 'EX-abc123def456';$url = "https://sandbox.boletocloud.com/api/v1/arquivos/cnab/remessas/$tokenArquivo";$api_key = 'api-key_SUA-API-KEY';
$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_USERPWD, "$api_key:token");curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_HEADER, true);
$response = curl_exec($ch);$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);$headers = substr($response, 0, $header_size);$body = substr($response, $header_size);curl_close($ch);
if ($http_code == 200) { preg_match('/filename=(.+)/', $headers, $matches); $filename = trim($matches[1] ?? 'remessa.rem'); file_put_contents($filename, $body); echo "Arquivo recuperado: $filename\n";} else { echo "Erro ($http_code): $body\n";}?>import reimport requestsfrom requests.auth import HTTPBasicAuth
token_arquivo = 'EX-abc123def456'
response = requests.get( 'https://sandbox.boletocloud.com/api/v1/arquivos/cnab/remessas/' + token_arquivo, auth=HTTPBasicAuth('api-key_SUA-API-KEY', 'token'))
if response.status_code == 200: match = re.search( r'filename=(.+)', response.headers.get('Content-Disposition', '') ) filename = match.group(1).strip() if match else 'remessa.rem'
with open(filename, 'wb') as f: f.write(response.content) print('Arquivo recuperado:', filename)
else: print('Erro:', response.status_code, '-', response.text)require 'net/http'require 'uri'
token_arquivo = 'EX-abc123def456'uri = URI("https://sandbox.boletocloud.com/api/v1/arquivos/cnab/remessas/#{token_arquivo}")
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http| request = Net::HTTP::Get.new(uri) request.basic_auth('api-key_SUA-API-KEY', 'token')
response = http.request(request)
if response.code == '200' filename = response['Content-Disposition'] &.match(/filename=(.+)/)&.[](1)&.strip || 'remessa.rem' File.write(filename, response.body) puts "Arquivo recuperado: #{filename}" else puts "Erro: #{response.code} - #{response.body}" endend(require '[clj-http.client :as client])
(let [token-arquivo "EX-abc123def456" response (client/get (str "https://sandbox.boletocloud.com/api/v1/arquivos/cnab/remessas/" token-arquivo) {:basic-auth ["api-key_SUA-API-KEY" "token"] :as :byte-array :throw-exceptions false})]
(if (= 200 (:status response)) (let [filename (or (second (re-find #"filename=(.+)" (get-in response [:headers "Content-Disposition"]))) "remessa.rem")] (clojure.java.io/copy (:body response) (clojure.java.io/file filename)) (println "Arquivo recuperado:" filename)) (println "Erro:" (:status response))))Exemplo Prático
Seção intitulada “Exemplo Prático”Cenário: Recuperação após Falha de Rede
Seção intitulada “Cenário: Recuperação após Falha de Rede”Durante a geração de uma remessa, a conexão foi interrompida após o servidor responder 201 Created, mas antes do arquivo ser completamente baixado.
- Chamada original:
POST /arquivos/cnab/remessasretornou201 Created - Problema: Timeout na rede, arquivo não foi recebido completamente
- Solução: Consultar Listar Remessas para obter o token
- Recuperação:
GET /arquivos/cnab/remessas/{token}para baixar o arquivo - Resultado: Arquivo recuperado integralmente
Resposta da API
Seção intitulada “Resposta da API”HTTP/1.1 200 OKContent-Type: text/plain; charset=utf-8Content-Disposition: inline; filename=CB070402.REMX-BoletoCloud-Version: 1.0.0