Payments Scheme
Troubleshooting

Rate Limits

Understand API rate limiting and how to handle rate limit errors

If you have questions or issues related to an API service in the Pilot or Live environments, please contact the Swift Customer Support Center.

Rate limiting controls the number of requests a client can make to an API within a given time period. It protects the API from being overwhelmed, prevents abuse, and ensures fair usage among all clients.

Rate limits are enforced at the institution level (BIC4).

How to interpret the setting value

For example, when you see a value of 50 ps in the setting column, then it means a minimum of 1000/50 = 20 milliseconds between 2 consecutive API calls.

APIPilotLive
Payment Pre-validation API100 ps100 ps
Tracker Frontend API100 ps100 ps
Network Interoperability100 ps100 ps

Handling rate limit errors

When you exceed the rate limit, the API returns HTTP status code 429 - Too Many Requests. This is a transient error, meaning your application should retry the request after a short delay.

HTTP 429 - Too Many Requests
{
  "severity": "Transient",
  "code": "SwAP507",
  "text": "Request cannot be processed at this time. Please try again."
}

Best practices

  • Implement throttling: Limit the rate of outgoing API calls from your application to stay within the allowed limits.
  • Use exponential backoff: When retrying after a 429 error, wait progressively longer between each retry attempt.
  • Monitor usage: Track your API call volume to identify patterns and optimise request frequency.

Example retry logic

async function callApiWithRetry(requestFn, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await requestFn();
    
    if (response.status === 429) {
      const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
      await new Promise(resolve => setTimeout(resolve, delay));
      continue;
    }
    
    return response;
  }
  throw new Error('Rate limit exceeded after maximum retries');
}
import time
import requests

def call_api_with_retry(request_fn, max_retries=3):
    for attempt in range(max_retries):
        response = request_fn()
        
        if response.status_code == 429:
            delay = (2 ** attempt)  # 1s, 2s, 4s
            time.sleep(delay)
            continue
        
        return response
    
    raise Exception('Rate limit exceeded after maximum retries')
public Response callApiWithRetry(Supplier<Response> requestFn, int maxRetries) 
    throws Exception {
    for (int attempt = 0; attempt < maxRetries; attempt++) {
        Response response = requestFn.get();
        
        if (response.getStatusCode() == 429) {
            long delay = (long) Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
            Thread.sleep(delay);
            continue;
        }
        
        return response;
    }
    throw new Exception("Rate limit exceeded after maximum retries");
}
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;

@Service
public class ApiService {

    private final RestTemplate restTemplate;

    public ApiService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @Retryable(
        retryFor = HttpClientErrorException.TooManyRequests.class,
        maxAttempts = 3,
        backoff = @Backoff(delay = 1000, multiplier = 2)
    )
    public ResponseEntity<String> callApiWithRetry(String url) {
        return restTemplate.getForEntity(url, String.class);
    }
}
public async Task<HttpResponseMessage> CallApiWithRetryAsync(
    Func<Task<HttpResponseMessage>> requestFn, 
    int maxRetries = 3)
{
    for (int attempt = 0; attempt < maxRetries; attempt++)
    {
        var response = await requestFn();
        
        if (response.StatusCode == HttpStatusCode.TooManyRequests)
        {
            var delay = (int)Math.Pow(2, attempt) * 1000; // 1s, 2s, 4s
            await Task.Delay(delay);
            continue;
        }
        
        return response;
    }
    throw new Exception("Rate limit exceeded after maximum retries");
}
package main

import (
	"errors"
	"math"
	"net/http"
	"time"
)

func callAPIWithRetry(requestFn func() (*http.Response, error), maxRetries int) (*http.Response, error) {
	for attempt := 0; attempt < maxRetries; attempt++ {
		response, err := requestFn()
		if err != nil {
			return nil, err
		}

		if response.StatusCode == http.StatusTooManyRequests {
			delay := time.Duration(math.Pow(2, float64(attempt))) * time.Second // 1s, 2s, 4s
			time.Sleep(delay)
			continue
		}

		return response, nil
	}
	return nil, errors.New("rate limit exceeded after maximum retries")
}

On this page