Platform API: Processing of API Rate Limits in a Connector for an External System
In MYOB Acumatica 2025.1, the built-in connectors for external systems (such as the BigCommerce, Amazon, and Shopify connectors) process responses with the 429 Too Many Requests response code differently. Previously, if the API rate limit of the external system was reached—that is, the 429 Too Many Requests response code was received—the built-in connector ignored this error and retried the request without a delay. This request failed in most cases. Now if the 429 Too Many Requests response code is received, the connector checks the headers of the response to find the recommended delay for the request, and retries the request after this delay.
If a developer implemented a custom connector by using the MYOB Acumatica Commerce Framework, the developer can update this connector to use the same approach for handling the 429 Too Many Requests response code. To use this approach, the developer needs to derive the REST API client implementation from the PX.Commerce.Core.REST.RetryCapableRESTClientBase abstract class and override its methods. The RetryCapableRESTClientBase class uses the Polly.Core.dll library.
The following code shows a sample fragment of the REST API client implementation for the BigCommerce connector.
public abstract class BCRestClientBase : RetryCapableRESTClientBase<BCRestClientBase.HttpCallContext> { protected override ValueTask<bool> IsFailure(Outcome<HttpCallContext> result, int attemptNumber, int attempts) => new((result.Exception is not null || (int)result.Result.Response.StatusCode is 429) && attempts >= attemptNumber); protected override ValueTask HandleError(HttpCallContext ctx, int attemptNumber, int attempts) { if (attempts == attemptNumber) throw new PXException(BCMessages.RetryLimitIsExceeded); return new ValueTask(); } protected override ValueTask<TimeSpan?> GetDelay(HttpCallContext context, int attemptNumber) { if (context is null) return new(TimeSpan.FromSeconds(attemptNumber + 1)); var response = context.Response; if ((int)response.StatusCode == 429) { if ((response.Headers.TryGetValues( BigCommerceConstants.Headers.RateLimitResetMs, out var values) || response.Headers.TryGetValues( BigCommerceConstants.Headers.RateLimitWindowMs, out values)) && int.TryParse(values.FirstOrDefault(), out var delay)) return new ValueTask<TimeSpan?>(TimeSpan.FromMilliseconds(delay)); return new ValueTask<TimeSpan?>(TimeSpan.FromSeconds(attemptNumber + 1)); } return new ValueTask<TimeSpan?>((TimeSpan?)null); } }
For more information about the implementation of a custom connector, see Implementing a Connector for an External System.