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}");
}