Skip to main content

Download a File

Retrieve the raw bytes of an inbound EDI parcel from your ECGrid mailbox and save them to disk (or pass them directly to your EDI parser).

Overview

After polling the inbox and getting a list of InBoxReady parcels, call the download endpoint for each parcelId. ECGrid returns the file content as a Base64-encoded payload (REST) or a byte array (SOAP). Decode it, write it to your destination, then immediately confirm the download so ECGrid marks the parcel as delivered.

Sequence:

  1. Poll inbox — obtain a list of parcel IDs (see Poll for Inbound Files).
  2. Download each parcel by ID — receive file bytes.
  3. Save the bytes to disk or hand them to your EDI processor.
  4. Confirm the download (see Confirm a Download).

:::warning Always Confirm After Saving If you download a parcel but do not confirm it, ECGrid will re-deliver the same file on the next poll. See Confirm a Download. :::


REST

Endpoint: POST /v2/parcels/download

Auth: X-API-Key: <key> header

Step 1 — Request the parcel content

POST https://rest.ecgrid.io/v2/parcels/download
Content-Type: application/json
X-API-Key: YOUR_API_KEY
{
"parcelId": 98765
}
FieldTypeRequiredDescription
parcelIdinteger (long)YesThe parcel ID from the inbox list response.

Step 2 — Handle the response

{
"success": true,
"data": {
"parcelId": 98765,
"fileName": "850_order.edi",
"content": "SVNBKDE...",
"contentEncoding": "Base64",
"size": 4096
}
}

Decode content from Base64 to obtain the raw EDI bytes, then write them to your destination path.

Code Examples

// .NET 10 — download a parcel and save to disk using IHttpClientFactory
// "ECGrid" named client is registered with base address and X-API-Key header

using System.Net.Http.Json;

public record DownloadRequest(long ParcelId);

public record ParcelContent(
long ParcelId,
string FileName,
string Content, // Base64-encoded file bytes
string ContentEncoding,
long Size);

public record DownloadResponse(bool Success, ParcelContent Data);

public class ECGridParcelDownloader
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger<ECGridParcelDownloader> _logger;

public ECGridParcelDownloader(
IHttpClientFactory httpClientFactory,
ILogger<ECGridParcelDownloader> logger)
{
_httpClientFactory = httpClientFactory;
_logger = logger;
}

/// <summary>
/// Downloads a parcel by ID and writes its content to the specified output path.
/// Returns the local file path on success. Throws on API or I/O error.
/// </summary>
public async Task<string> DownloadToFileAsync(
long parcelId,
string outputDirectory,
CancellationToken cancellationToken = default)
{
var http = _httpClientFactory.CreateClient("ECGrid");

var response = await http.PostAsJsonAsync(
"/v2/parcels/download",
new DownloadRequest(parcelId),
cancellationToken);

response.EnsureSuccessStatusCode();

var result = await response.Content
.ReadFromJsonAsync<DownloadResponse>(cancellationToken: cancellationToken)
?? throw new InvalidOperationException("Empty response from download endpoint.");

if (!result.Success)
throw new InvalidOperationException($"Download failed for parcelId={parcelId}.");

// Decode Base64 content to raw bytes
byte[] fileBytes = Convert.FromBase64String(result.Data.Content);

// Build a safe output path — use the server-supplied filename
string safeFileName = Path.GetFileName(result.Data.FileName); // strip any path components
string outputPath = Path.Combine(outputDirectory, safeFileName);

await File.WriteAllBytesAsync(outputPath, fileBytes, cancellationToken);

_logger.LogInformation(
"Saved parcel {ParcelId} → {Path} ({Bytes} bytes)",
parcelId, outputPath, fileBytes.Length);

return outputPath;
}
}

Usage in your polling loop:

foreach (var parcel in readyParcels)
{
var savedPath = await downloader.DownloadToFileAsync(
parcel.ParcelId,
outputDirectory: "/data/edi/inbound",
cancellationToken);

// Process EDI content here, then confirm
await confirmer.ConfirmAsync(parcel.ParcelId, cancellationToken);
}

SOAP

:::caution Established API The SOAP API is in maintenance mode. For new integrations use REST above. :::

Method: ParcelDownload(SessionID, ParcelID)byte[]

Step 1 — Call ParcelDownload

var result = await client.ParcelDownloadAsync(sessionId, parcelId);
byte[] fileBytes = result.ParcelDownloadResult;

The method returns the raw file bytes directly — no Base64 decoding required.

Step 2 — Save to disk

await File.WriteAllBytesAsync(outputPath, fileBytes);

Code Examples

// .NET 10 — dotnet-svcutil generated proxy
// Reference: https://os.ecgrid.io/v4.1/prod/ECGridOS.asmx?WSDL

using ECGridOS;

public static async Task DownloadParcelAsync(
ECGridOSAPIClient client,
string sessionId,
int parcelId,
string outputDirectory)
{
// Fetch parcel metadata first to get the filename
var infoResult = await client.ParcelInfoAsync(sessionId, parcelId);
var info = infoResult.ParcelInfoResult;
string safeFileName = Path.GetFileName(info.FileName);

// Download the raw bytes
var download = await client.ParcelDownloadAsync(sessionId, parcelId);
byte[] fileBytes = download.ParcelDownloadResult;

string outputPath = Path.Combine(outputDirectory, safeFileName);
await File.WriteAllBytesAsync(outputPath, fileBytes);

Console.WriteLine($"Saved: {outputPath} ({fileBytes.Length} bytes)");

// Confirm immediately after saving — see confirm-download.md
await client.ParcelDownloadConfirmAsync(sessionId, parcelId);
Console.WriteLine($"Confirmed parcelId={parcelId}");
}