API Errors
This page outlines errors encountered when using Topsort’s /auctions and /events endpoints or APIs, classified by HTTP status code:
4xx: Request problem
5xx: Topsort service problem
Both errors return JSON arrays containing error objects with fields: errCode, docUrl, and an optional message.
| Field | Type | Description | 
|---|---|---|
| errCode | string | A short string uniquely identifying the problem. | 
| docUrl | string | A link to this documentation providing more information about the error. | 
| message | string | Optional. If present, human-readable explanation of or details about the error. The string for a given error may change over time; code should not parse or dispatch based on particular values for this field. | 
Error Codes and Meanings:
| Code | Description | Details | ||
|---|---|---|---|---|
| 400 | Bad Request | Unacceptable request, i.e. Incorrect formatting | ||
| 403 | Forbidden/Unauthorized | API key issue or missing tokens | ||
| 404 | Not Found | The server cannot find the requested resource. Either the request URL is not on our routes, or the resource is not available (ie. the requested campaign does not exist) | ||
| 422 | Unprocessable Entity | Mismatched request body and model, i.e, you are missing a property, or API is expecting a date but received a number | ||
| 429 | Rate Limit Exceeded | IP-based rate limit reached. This error comes with following headers:  - X-RateLimit-Limit: total number of requests allowed for the time period - X-RateLimit-Remaining: remaining number of requests for the time period - X-RateLimit-Reset: when you can make another request | 
Error Codes
| Error Code | Description | 
|---|---|
| bad_request | Request couldn’t be parsed; check the OpenAPI specification for the correct schema. | 
| empty_request | Request is empty; check the OpenAPI specification for the correct schema. | 
| internal_server_error | Unexpected server problem; our team typically fixes these issues quickly. | 
| invalid_api_key | Missing, invalid, or expired API key; see authentication for details. | 
| invalid_auction_id | Auction ID doesn’t correspond to an auction; ensure a valid auction ID is passed in the request. | 
| invalid_event_type | Event type must be “Impression”, “Click”, or “Purchase”. | 
| invalid_promotion_type | Invalid promotion types in slots field. | 
| invalid_session | session object must contain a non-empty sessionId. | 
| missing_aspect_ratio | Required aspect ratio for banner ads is missing. | 
| missing_auctions | At least one auction must be specified. | 
| missing_context | Required context missing; specify a category, product list, or search query. | 
| missing_placement | Required placement or placement.page field is missing. | 
| missing_product_id | productId missing. | 
| missing_promotion_type | An auction must request slots for at least one promotion type. | 
| missing_purchased_at | Required purchasedAt field missing. | 
| missing_session | Required session field missing. | 
| missing_slots | Required slots field missing. | 
| no_products | At least one product must be specified. | 
| no_purchase_items | At least one item must be purchased. | 
| purchase_item_quantity_less_or_equal_than_zero | A purchase item has a quantity of less than or equal to zero. | 
| resolved_bid_id_not_found | Provided resolved bid ID doesn’t match an internal record. | 
| too_few_impressions | At least one impression must be included. | 
| too_few_slots | At least one slot must be specified in an auction. | 
| too_many_auctions | Maximum of 5 auctions can run in parallel; contact your KAM to increase this limit. | 
Handling rate limiting
Our endpoints - except making calls to /auctions or /events - are rate-limited to prevent abuse. If you exceed the rate limit, you will receive a 429 error response. There are two recommended ways to handle these limits
Retry with exponential back-off
Exponential backoff retry is a technique used in programming to retry an operation with increasing intervals between retries, which helps to mitigate issues such as network latency, temporary failures, or resource constraints. Below there is a code example in Python on how the technique can be implemented.
def exponential_backoff_retry(url, max_retries=5, base_delay=1, max_delay=64, retry_on_status=429):    retries = 0    delay = base_delay    while retries < max_retries:        try:            response = requests.get(url)            if response.status_code == retry_on_status:                print(f"Received status code {retry_on_status}, retrying...")                retries += 1                if retries < max_retries:                    print(f"Retrying in {delay} seconds...")                    time.sleep(delay)                    delay = min(delay * 2, max_delay)                else:                    raise Exception(f"All retries exhausted for status code {retry_on_status}")            else:                response.raise_for_status()  # Raise an exception for HTTP errors other than the specified one                return response.json()  # Assuming the response is JSON, adjust as needed        except Exception as e:            print(f"Attempt {retries + 1}/{max_retries} failed: {e}")            retries += 1            if retries < max_retries:                print(f"Retrying in {delay} seconds...")                time.sleep(delay)                delay = min(delay * 2, max_delay)            else:                raiseUse Retry-After
Use the values in the headers to determine when you can make another request:
X-RateLimit-Limit: how many requests you have made during the time periodX-RateLimit-Remaining: remaining request during the time periodX-RateLimit-Reset: when you can make another request
Note that if you have distributed services hitting the resource, you can still get
429, even if you waited the time amount specified in X-RateLimit-Reset. If you
are hitting this problem, you may want to either replace this technique with the
Exponential back-off or use them together, that is, first waiting the amount of
time given by X-RateLimit-Reset and then fall-back to exponential back-off retries.