We’re experiencing intermittent 500 errors when posting batches of invoices through the Accounts Receivable REST API in ICS 2021. The batch contains 50-100 invoices and fails randomly around invoice 30-40. When we retry the same batch, some invoices get duplicated while others are skipped entirely.
We’re concerned about batch transaction atomicity - should the entire batch rollback on error? We’ve also noticed the API doesn’t seem to support idempotency keys in the request headers. Here’s our current posting approach:
POST /api/v1/invoices/batch
{
"invoices": [{"invoiceNumber": "INV-001", "amount": 1500.00}, ...]
}
What’s the best practice for API error handling in batch scenarios? Should we switch to individual POST requests with retry logic, or is there a better way to ensure data consistency?
Another critical point - always include a unique external reference ID in each invoice payload. Even if you get a timeout error, you can query the AR module afterwards using that external reference to check if the invoice was actually created. We use a combination of timestamp and sequence number for this. Also consider implementing exponential backoff for retries - immediate retries often hit the same timeout issue.
The ICS 2021 batch API doesn’t support true atomic transactions across the entire batch. Each invoice in the batch is processed sequentially, and if one fails, the previous ones remain committed. This is documented behavior, though not well publicized. You need to implement idempotency at the application layer since the API doesn’t provide native support for it.
Thanks for the insights. So if I understand correctly, we need to handle idempotency ourselves? How would you recommend tracking which invoices were successfully posted versus which ones failed or need retry?
I ran into this last year and spent weeks debugging. The duplicate invoice problem you’re seeing happens because the API doesn’t check for existing invoices by external reference before creating them. Here’s the pattern we settled on that addresses all three key concerns:
Batch Transaction Atomicity: Split large batches into micro-batches of 10-15 invoices. This keeps processing time under 30 seconds and reduces the blast radius of failures. Wrap each micro-batch in your own transaction tracking.
Idempotency Key Usage: Since the API doesn’t support native idempotency headers, implement it at the application layer:
// Generate idempotency key per invoice
const idempotencyKey = `${companyId}-${invoiceDate}-${invoiceNumber}`;
// Check staging table before API call
IF NOT EXISTS in staging_table WHERE idempotency_key = idempotencyKey
THEN call API and insert into staging_table
API Error Handling Best Practices:
- Implement a three-tier retry strategy: immediate retry (network blips), delayed retry after 5 minutes (temporary API issues), manual review queue (persistent failures)
- Parse the 500 error response body - sometimes it contains partial success information indicating which invoices were actually posted
- Use the AR query API to verify invoice existence before retry: `GET /api/v1/invoices?externalRef={yourRef}
- Log every API request/response with correlation IDs for troubleshooting
POST /api/v1/invoices
Headers: {"X-Correlation-ID": "uuid-here"}
{
"externalReference": "BATCH-2025-03-15-001-INV-001",
"invoiceNumber": "INV-001"
}
For the duplicates you’re experiencing, run a cleanup script that queries invoices by external reference and voids duplicates created within the same hour. We also added a pre-flight check that queries existing invoices for the date range before posting to catch potential duplicates early.
One more thing - enable detailed API logging in Infor OS Gateway settings. The default logging level misses crucial details about why batches fail. Set it to DEBUG temporarily to capture the full request/response cycle, then analyze the patterns. In our case, we discovered that invoices with special characters in customer names were causing silent failures mid-batch.
This approach reduced our failure rate from 15% to under 1%, and eliminated duplicates entirely. The key is accepting that the API doesn’t provide atomic batch operations and building that reliability layer yourself.
We built a staging table approach for this exact scenario. Before calling the API, insert all invoices into a staging table with status=‘PENDING’. After each successful API call, update that specific invoice to status=‘POSTED’ with the API response ID. If the batch fails, you can query for PENDING records and retry only those. This gives you idempotency through your own tracking mechanism. We also reduced our batch size to 25 invoices to stay well under the timeout threshold.
I’ve seen this exact issue. The Infor OS API Gateway has a 60-second timeout for batch operations, and if your batch processing exceeds that, you get the 500 error mid-stream. The real problem is that some invoices have already been committed to the database before the timeout hits. Check your API gateway logs - you’ll likely see timeout warnings.