Skip to main content

Poll for Inbound Files

Periodically check your ECGrid mailbox for EDI files that are ready to download. This is the first step of every inbound EDI integration loop.

Overview

ECGrid queues inbound EDI parcels in your mailbox as they arrive. Your integration polls the inbox list endpoint on a schedule, retrieves the list of parcels in InBoxReady status, then downloads and confirms each one. In production, the poll loop typically runs as a BackgroundService (Worker Service) or a scheduled job on a 1–15 minute interval.

Sequence:

  1. Call the inbox list endpoint with your mailbox credentials and a page size.
  2. Receive a list of parcel summary records.
  3. For each record — download, process, and confirm.

REST

Endpoint: POST /v2/parcels/pending-inbox-list

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

Step 1 — Request the inbox list

POST https://rest.ecgrid.io/v2/parcels/pending-inbox-list
Content-Type: application/json
X-API-Key: YOUR_API_KEY
{
"mailboxId": 0,
"pageNo": 1,
"recordsPerPage": 25
}
FieldTypeDescription
mailboxIdintegerYour mailbox ID. Pass 0 to use the default mailbox for the API key.
pageNointeger1-based page number for pagination.
recordsPerPageintegerMaximum records per page. Typical values: 25–100.

Step 2 — Inspect the response

{
"success": true,
"data": [
{
"parcelId": 98765,
"fileName": "850_order.edi",
"fromECGridId": 123456,
"toECGridId": 789012,
"status": "InBoxReady",
"receivedDate": "2026-05-07T14:32:00Z",
"size": 4096
}
],
"totalRecords": 3,
"pageNo": 1,
"recordsPerPage": 25
}

Iterate over data. For each parcel, proceed to Download a File and then Confirm Download.

Code Examples

// .NET 10 — poll inbox using IHttpClientFactory (register in DI as "ECGrid")
// Load API key from IConfiguration, not hardcoded

using System.Net.Http.Json;
using System.Text.Json.Serialization;

public record PendingInboxListRequest(
int MailboxId,
int PageNo,
int RecordsPerPage);

public record ParcelSummary(
long ParcelId,
string FileName,
int FromECGridId,
int ToECGridId,
string Status,
DateTimeOffset ReceivedDate,
long Size);

public record InboxListResponse(
bool Success,
List<ParcelSummary> Data,
int TotalRecords,
int PageNo,
int RecordsPerPage);

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

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

/// <summary>
/// Retrieves all InBoxReady parcels, paging through results until the list is exhausted.
/// </summary>
public async Task<List<ParcelSummary>> GetAllReadyParcelsAsync(
int mailboxId,
CancellationToken cancellationToken = default)
{
var http = _httpClientFactory.CreateClient("ECGrid");
var allParcels = new List<ParcelSummary>();
int pageNo = 1;
const int pageSize = 25;

while (true)
{
var request = new PendingInboxListRequest(mailboxId, pageNo, pageSize);
var response = await http.PostAsJsonAsync(
"/v2/parcels/pending-inbox-list", request, cancellationToken);

response.EnsureSuccessStatusCode();

var result = await response.Content
.ReadFromJsonAsync<InboxListResponse>(cancellationToken: cancellationToken);

if (result is null || result.Data.Count == 0)
break;

allParcels.AddRange(result.Data);
_logger.LogInformation(
"Fetched page {Page}: {Count} parcel(s)", pageNo, result.Data.Count);

// Stop paging when we have received fewer records than the page size
if (result.Data.Count < pageSize)
break;

pageNo++;
}

_logger.LogInformation("Total parcels ready: {Total}", allParcels.Count);
return allParcels;
}
}

Registration in Program.cs:

// Register named HTTP client with base address and auth header
builder.Services.AddHttpClient("ECGrid", client =>
{
client.BaseAddress = new Uri("https://rest.ecgrid.io");
client.DefaultRequestHeaders.Add(
"X-API-Key",
builder.Configuration["ECGrid:ApiKey"]);
});

builder.Services.AddScoped<ECGridInboxPoller>();

:::tip Production Polling Pattern In production, run the polling loop inside an IHostedService / BackgroundService with a configurable interval. Use PeriodicTimer (.NET 6+) rather than Task.Delay to avoid drift.

// Inside ExecuteAsync() of your BackgroundService
using var timer = new PeriodicTimer(TimeSpan.FromMinutes(5));
while (await timer.WaitForNextTickAsync(stoppingToken))
{
var parcels = await _poller.GetAllReadyParcelsAsync(mailboxId, stoppingToken);
foreach (var parcel in parcels)
await ProcessParcelAsync(parcel, stoppingToken);
}

:::


SOAP

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

Method: ParcelInBox(SessionID, NetworkID, MailboxID, ECGridIDFrom, ECGridIDTo, Status, BeginDate, EndDate, PageNo, RecordsPerPage)

Step 1 — Log in and get a session ID

var session = await client.LoginAsync("username", "password");
string sessionId = session.LoginResult;

Step 2 — Call ParcelInBox

var result = await client.ParcelInBoxAsync(
sessionId,
networkId: 0, // 0 = default for session
mailboxId: 0, // 0 = default for session
ecgridIdFrom: 0, // 0 = any sender
ecgridIdTo: 0, // 0 = any recipient
status: ParcelStatus.InBoxReady,
beginDate: DateTime.MinValue,
endDate: DateTime.MaxValue,
pageNo: 1,
recordsPerPage: 25);

foreach (var parcel in result.ParcelInBoxResult ?? [])
{
Console.WriteLine($"ParcelID={parcel.ParcelID} File={parcel.FileName} Size={parcel.Size}");
}

Code Examples

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

using ECGridOS; // namespace from generated proxy

var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
var endpoint = new EndpointAddress("https://os.ecgrid.io/v4.1/prod/ECGridOS.asmx");
var client = new ECGridOSAPIClient(binding, endpoint);

string sessionId = string.Empty;

try
{
// Obtain session — store and reuse; do not call Login() on every poll
var loginResult = await client.LoginAsync(
Environment.GetEnvironmentVariable("ECGRID_USER")!,
Environment.GetEnvironmentVariable("ECGRID_PASS")!);
sessionId = loginResult.LoginResult;

int pageNo = 1;
const int pageSize = 25;

while (true)
{
var inbox = await client.ParcelInBoxAsync(
sessionId,
networkId: 0,
mailboxId: 0,
ecgridIdFrom: 0,
ecgridIdTo: 0,
status: ParcelStatus.InBoxReady,
beginDate: DateTime.MinValue,
endDate: DateTime.MaxValue,
pageNo: pageNo,
recordsPerPage: pageSize);

var parcels = inbox.ParcelInBoxResult;
if (parcels is null || parcels.Length == 0)
break;

foreach (var p in parcels)
Console.WriteLine($"Ready: ParcelID={p.ParcelID} File={p.FileName}");

if (parcels.Length < pageSize)
break;

pageNo++;
}
}
finally
{
// Always log out to release the session slot
if (!string.IsNullOrEmpty(sessionId))
await client.LogoutAsync(sessionId);
}

:::tip Reuse the Session The SOAP SessionID is valid for the duration of a session. Do not call Login() on every poll iteration — obtain the session once at startup and renew it only when it expires. :::