Skip to main content
2025-R1Platform

Platform API: Processing of API Rate Limits in a Connector for an External System

Last updated: 31 October 2025

Platform API: Processing of API Rate Limits in a Connector for an External System

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 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.