The Measurement API has rate limits in place to help ensure the availability of the service and prevent accidental plan overages. Rate limits are implemented per-game or API key as outlined in the table below
Endpoint | Rate Limit | Can be increased? |
---|---|---|
/events requests per second | 500 | Yes |
/events/batch requests per minute | 500 | Yes |
If you exceed these limits on your requests, you will begin to receive HTTP 429 Too Many Requests
response.
Limit Increases
If your integration will consistently be exceeding the default rate limits outlined above please contact your account manager who can help review your use case and raise your account limits.
Rate Limit Headers
The API returns several rate limit headers to help you implement throttling and retry mechanisms into your client
x-ratelimit-limit
- The maximum number of requests permitted per time window. Formatted as defined in IEFT Proposal for Rate Limit Headers.x-ratelimit-remaining
- Indicates the number of remaining requests that you can make in the current time windowx-ratelimit-reset
- The number of seconds until your rate limit resets for this endpoint
For example, if you receive a remaining
value of 10 and a reset
value of 60 then your client is allowed to make 10 more requests in the next 60 seconds before you would start to receive a 429 Too Many Requests
response from the API.
Example
Below is a working Python example implementation that includes automated retries, backoff, and rate limit handling. This can be a good starting point when designing the error handling for your API integration.
import requests
import time
def send_events(events, retry_limit=15):
"""Send a batch of events to the Gamesight API.
Args:
events (list): List of events to send.
retry_limit (int): Number of times to retry the request if it fails.
Returns:
bool: True if the request was successful, False otherwise.
"""
attempts = 0
while attempts < retry_limit:
attempts += 1
try:
response = requests.post(
"https://api.ingest.marketing.gamesight.io/events/batch",
headers = {"Authorization": "YOUR_API_KEY"},
json = {"events": events}
)
except requests.exceptions.RequestException as e:
print(f"Request failed with exception: {e}, retrying. Attempt {attempts}")
time.sleep(0.5 * attempts)
continue
rate_limit_remaining = int(response.headers.get('x-ratelimit-remaining', 0))
if response.status_code == 201:
print("Request successful, rate limit remaining:", rate_limit_remaining)
return True
# If status is 422, the request was invalid and should not be retried
elif response.status_code == 422:
print("Invalid payload, skipping batch", response.json())
return False
print(f"Request failed with status code {response.status_code}, retrying")
if rate_limit_remaining <= 1:
# This is a rate limit error, we should wait for the rate limit to reset
sleep_duration = int(response.headers.get('x-ratelimit-reset', 10))
print(f"Rate limit reached. Sleeping for {sleep_duration} seconds.")
time.sleep(sleep_duration)
else:
# Exponential backoff if the error is not rate limiting
time.sleep(0.5 * attempts)
print("Reached retry limit, skipping batch")
return False
if __name__ == "__main__":
# Generate test events
events = [
{"type": "test", "user_id": "test-user-123", "identifiers": {}} for _ in range(1000)
]
# Send is batches of batch_size
batch_size = 10
while len(events) > 0:
batch = events[:batch_size]
send_events(batch)
events = events[batch_size:]
print("Done")