---
url: https://docs.dataflair.ai/marketplace/ad-server-api/retries-and-idempotency.md
description: >-
  What DataFlair does when your server is slow or returns an error, the real
  timeouts, where no retry exists, and how a repeated booking stays safe.
---

# Retries and idempotency

This page says what DataFlair does when your server is slow, returns an error, or receives the same request twice. It separates what the platform does **today** from what the **contract** describes for calls that are not live yet.

## Timeouts

DataFlair waits up to **10 seconds** to connect to your server and up to **30 seconds** in total for one call. These are the platform's configured defaults. They apply to every call to your server.

## Retries today

Today DataFlair calls two endpoints: [`GET /health`](/marketplace/ad-server-api/operations/health) and [`GET /inventory`](/marketplace/ad-server-api/operations/inventory), when an operator connects or re-verifies.

**Neither call is retried.** If it fails, DataFlair records the failure, and the operator presses **Re-verify** in DataFlair after fixing the cause.

Other facts about how DataFlair makes these calls:

* DataFlair does not follow redirects. A `3xx` answer is not followed.
* DataFlair resolves your host on every call. The host must resolve to public addresses only.
* Only `GET /health` decides the connection state. A failed `GET /inventory` leaves Inventory read as **Not verified** and does not fail the connection.

## Calls that are not live yet

DataFlair does not call `POST /forecast`, `POST /orders` or `POST /reports` yet. No retry behaviour exists for them in the platform. The contract asks you to expect the reactions below when they go live. Treat the table as the contract and not as current behaviour.

| Your answer | Contract: what DataFlair does |
| --- | --- |
| `429` with `Retry-After` | Backs off for that many seconds, then retries. |
| `5xx`, or no answer | Retries with backoff. A persistent failure shows as "your platform is unreachable". |
| `409` | Logs it. Does not retry it blindly. |
| `404` | Skips that item and reports it. |
| `422` | Shows your `message` to the operator. Does not retry. |
| `501` on `POST /forecast` | Treats the slot as "no forecast available". |

The contract also says DataFlair may send `POST /orders` again for the same campaign. It happens when a publisher clicks "re-push", and when a later creative approval re-traffics. It can also happen on an automatic retry.

## Idempotency for `POST /orders`

A booking can arrive more than once. Your API must make a repeat safe. There are two cases, and they use different keys.

| Case | What arrives | What you do |
| --- | --- | --- |
| **A literal retry** | The same `idempotency_key` and the same body. | Return the same result with `200`. Create nothing new. |
| **A conflict** | The same `idempotency_key` and a different body. | Reject it with `409`. Do not guess which body is right. |
| **An update** | A new `idempotency_key` and the same `order.external_ref` and `line_items[].external_ref`. | Match on `external_ref`. Update only what changed. Return the same `order_id` and `line_item_id` values with `200`. |

Read calls (`/health`, `/inventory`, `/forecast`, `/reports`) are idempotent by nature. DataFlair can repeat them freely.

The full rules and an example are on [POST /orders](/marketplace/ad-server-api/operations/orders#idempotency-and-recovery) and in [Conventions](/marketplace/ad-server-api/conventions#idempotency).

## What to build now

* Answer every call inside 30 seconds, and connect inside 10 seconds. A slow answer counts as a failure.
* Return `429` with `Retry-After` when you need DataFlair to slow down.
* Make `POST /orders` idempotent as described above, even though DataFlair does not call it yet.
