Skip to content

We call youDataFlair calls YOUR server. You implement this endpoint. You do not call DataFlair.

Conformance check ​

The conformance check replays the fixtures against your ad server. It prints one line for each case. A failing line says what is wrong and links to the section that explains it.

It runs on your own machine, against localhost or a staging server. It does not need a DataFlair account. It checks each answer against the schemas in the OpenAPI file, the same file the API reference is built from, so the check and the reference cannot disagree.

The checker is not published to npm yet

npx cannot fetch it yet. It is in the DataFlair docs repository, in docs-site/tools/adserver-check. Run it from the docs-site folder, after npm ci. The fixtures work without it: send each request.json with curl and compare the answer with expected-response.json.

Run it ​

bash
node tools/adserver-check/bin/adserver-check.mjs http://localhost:3000/api/v1 --key sk_test_local

Use the base URL you give DataFlair, and a test key. A command line stays in your shell history, so you can set ADSERVER_CHECK_KEY instead of --key.

OptionMeaning
--key <key>The key to send as a Bearer token. Or set ADSERVER_CHECK_KEY.
--only <endpoint>Run one endpoint: health, inventory, forecast, orders or reports.
--slot <inventory_id>Book against this slot, instead of the first slot that GET /inventory lists.
--docs <url>Where the failure links point. The default is https://docs.dataflair.ai.
--fixtures <folder>Replay a folder of fixtures instead of the bundled ones.

The exit code is 0 when your server is ready to connect, 1 when a case failed, and 2 when the command was used wrongly.

A passing run ​

Every case passes against a server that follows the contract:

text
✓ GET  /health         200  Returns the account and its capabilities
✓ GET  /health         401  A wrong key is a 401 with an error body
✓ GET  /inventory      200  Lists the bookable slots
✓ POST /forecast       200  Returns available and forecasted impressions
✓ POST /forecast       404  An unknown inventory_id is a 404 with an error body
✓ POST /orders         201  Creates a draft order
✓ POST /orders         409  The same idempotency_key with a different body is a 409
✓ POST /orders         201  A booking with no creative still returns draft line items that do not serve
✓ POST /orders         200  A repeat of the same idempotency_key and body returns the same ids
✓ POST /orders         404  An unknown inventory_id is a 404 with an error body
✓ POST /orders         200  A new idempotency_key with the same external_ref updates the existing order
✓ POST /reports        200  Returns impressions and clicks per line
✓ POST /reports        200  granularity daily returns a date on every row

13 passed · 0 failed. Ready to connect.

A failing run ​

Here a server returns its orders as ACTIVE. The check was run with --only orders. Each failing line names the value and links to the draft-only rule:

text
✗ POST /orders         201  Creates a draft order
    Order "ord_55021" returned as "ACTIVE". It must come back as DRAFT and must not serve.
    Line item "li_88012" returned as "ACTIVE". Every line item must come back as DRAFT and must not serve.
    → See https://docs.dataflair.ai/marketplace/ad-server-api/operations/orders#draft-only
✓ POST /orders         409  The same idempotency_key with a different body is a 409
✗ POST /orders         201  A booking with no creative still returns draft line items that do not serve
    Order "ord_55022" returned as "ACTIVE". It must come back as DRAFT and must not serve.
    Line item "li_88013" returned as "ACTIVE". Every line item must come back as DRAFT and must not serve.
    → See https://docs.dataflair.ai/marketplace/ad-server-api/operations/orders#draft-only
✗ POST /orders         200  A repeat of the same idempotency_key and body returns the same ids
    Order "ord_55021" returned as "ACTIVE". It must come back as DRAFT and must not serve.
    Line item "li_88012" returned as "ACTIVE". Every line item must come back as DRAFT and must not serve.
    → See https://docs.dataflair.ai/marketplace/ad-server-api/operations/orders#draft-only
✓ POST /orders         404  An unknown inventory_id is a 404 with an error body
✗ POST /orders         200  A new idempotency_key with the same external_ref updates the existing order
    Order "ord_55021" returned as "ACTIVE". It must come back as DRAFT and must not serve.
    Line item "li_88012" returned as "ACTIVE". Every line item must come back as DRAFT and must not serve.
    → See https://docs.dataflair.ai/marketplace/ad-server-api/operations/orders#draft-only

2 passed · 4 failed. Not ready to connect.

What it sends and changes ​

The requests are the fixtures. The check changes three things and nothing else:

  1. The campaign token. The examples use the token VDWZQ4IT in every key, order name and external_ref. Each run swaps it for a fresh one, so you can run the check again without replaying the last run's keys.
  2. The slot. The examples book slot_728x90_home. The check reads GET /inventory and books the first slot that is not archived, and it prefers a slot that takes 728x90. Pass --slot to choose one. The unknown-slot cases keep slot_x.
  3. The line item ids in the reports request. The check sends the ids your server returned from POST /orders, not the example ids.

The wrong-key case sends a generated key. Nothing else in a request is changed.

The booking cases create draft orders on your server, named Summer Launch (DF-CMP-...) and similar. Delete them when you are done.

With --only, the check first reads what the endpoint needs, without printing it. --only forecast, --only orders and --only reports read GET /inventory for a slot. --only forecast also reads GET /health. --only reports then books one draft order, because reports asks about a line item.

What it checks ​

Every case checks that your server answered, that it did not redirect, that the status is the expected one, and that the body fits the schema. DataFlair does not follow redirects, so a redirect fails the case. If your server does not answer the first request at all, the check stops there and marks the rest as not run.

If GET /health says forecast is false, the forecast cases are skipped. DataFlair does not call POST /forecast then. A skipped case is not a pass. A run where every case was skipped is not ready to connect.

These rules apply on top of the schema:

RuleWhat it checksExplained in
health.requiredCapabilitiesreporting and draft_booking are not false.Fields
forecast.echoesSlotThe answer names the slot that was asked about.What you return
forecast.orderingavailable_impressions is not higher than forecasted_impressions.What you return
orders.draftOnlyThe order and every line item come back as DRAFT.Draft only
orders.echoesExternalRefsEvery external_ref that was sent comes back, and no other.What you return
orders.sameIdsAsCreateA repeat or an update returns the same order_id and line_item_id values as the first call.Idempotency and recovery
reports.rowsForRequestedLinesEvery row is for a line that was asked about, with one row per line, or one per line per day.What you return
reports.dailyHasDateWith granularity set to daily, every row has a date.What you return

What it does not check ​

  • It reads only the first page of GET /inventory.
  • It waits up to 30 seconds for each answer. It does not measure speed.
  • It reads the state your server says it returned. It cannot tell whether a draft really stays out of serving. Look at the drafts in your console.
  • It does not test how DataFlair behaves. It tests your server.

If a case fails, follow its link. Errors and Troubleshooting cover the rest.

Docs version 1.0.1