> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shftd2.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Publishers integrate one API: GET https://api.shftd2.com/v1/fragment?partner_id=<account id>&page_url=<page URL>, called from their edge for AI-agent requests only, with the API key in the X-API-Key header, never in the query string.
> A 200 carries the card. A 204 means no card: serve the page unchanged.
> The management API (https://api.shftd2.com/v1/me, /v1/sites, /v1/cards, /v1/keys) is optional tooling for scripting setup. It takes its own management token (Authorization: Bearer ds_mgmt_…). Its limits (120 requests and 60 writes per minute per token) do not apply to the delivery API.
> Delivery logs reach doubleshift only through direct delivery logs (POST https://logs.shftd2.com/v1/beacon with a logs token; the edge library with a logsToken is its provided client, and a custom sender may use the same endpoint) or a Cloudflare Logpush job configured with doubleshift. Otherwise doubleshift sees only its own API activity.

# How delivery works

> The rules behind every card call: how a page URL resolves to a site and a fragment, how a card is chosen, why nothing is cached, and where the card lands in the page.

For an AI-agent request, your edge sends doubleshift two values: your account id (`partner_id`) and
the page URL (`page_url`). doubleshift finds the fragment for that page, picks one eligible card, and
answers with the card (`200`) or a no-fill (`204`). A human request never reaches doubleshift, and
the answer never depends on the visitor's `User-Agent`: that value only feeds reporting.

Every other page of these docs links here instead of restating these rules.

![Data model: an account owns sites, each site owns fragments; cards carry an advertiser\_id](https://mintcdn.com/doubleshift/sw4Ab4HuCk7yFPgK/images/diagrams/data-model-lt.svg?fit=max\&auto=format\&n=sw4Ab4HuCk7yFPgK\&q=85\&s=b9db0101cc6cdc248964cbe830e616f4)

An account owns sites; each site owns fragments. Cards carry an advertiser\_id and can be restricted to selected fragments through their eligibility.

* A **site** is a domain you publish on. See [Sites and fragments](https://docs.shftd2.com/sites.md).
* A **fragment** is one card slot on a site. Your edge never names it: doubleshift resolves it from
  the page URL.
* A **card** is the branded-content article served to an agent. Its **eligibility** says on which
  fragments it may serve. See [Cards](https://docs.shftd2.com/cards.md).

## Resolution

doubleshift resolves `page_url` to one fragment, within the account your API key belongs to. Only
the `X-API-Key` header authenticates the call; see [API keys](https://docs.shftd2.com/api-keys.md).

**1. The host finds the site.** The page's hostname is lowercased, without its port or a trailing
dot. A site registered under that exact hostname wins. Otherwise its `www.` or bare-domain alias can
match: `www.your-domain.example` and `your-domain.example` reach the same site when only one of them
is registered. A host that matches no site of your account answers `204`.

**2. The path is put in canonical form.** The query string and the hash are ignored, so
`?utm=campaign` or `#top` never change the result. Each path segment is decoded and re-encoded, so
`/%c3%a9conomie`, `/%C3%A9conomie` and `/économie` are the same path. Trailing slashes are dropped,
then the path is lowercased and ends with a single `/` (`/` for the homepage). Routing rules are
stored in that same form, which is why the console turns `Actualite/` into `/actualite/`. This
lowercased form is the routing path only: the card pick keeps the case ([selection](#selection)).

**3. The path finds the fragment.** In this order:

1. An **exact** routing rule equal to the path. An exact `/news/` matches `/news` and `/news/`, and
   an exact `/` matches the homepage only.
2. The **longest prefix** rule the path starts with. A prefix `/news/` matches `/news/article`; a
   prefix `/` covers the whole site.
3. The site's **default fragment**.

Nothing matches, and the site has no default: `204`.

**4. The fragment's status is read last.** A paused fragment answers `204`, even if a shorter rule or
the site default points to an active one. There is no fallback once a fragment is resolved.

A `page_url` without a usable `http` or `https` host, or longer than 2,048 characters, answers `204`
before the key is even checked.

## Selection

Once the fragment is resolved, doubleshift chooses the card in two moves.

**1. The eligible pool.** It starts from the active cards of your account and the active platform
cards. A card with no fragment selected in its eligibility is eligible everywhere. A card with one or
more fragments selected is eligible on those fragments only. Several cards can be eligible on the
same fragment, and eligibility gives no priority: it only says where a card may serve.

**2. A stable pick by page.** doubleshift orders the pool and picks one card from a hash of the page
key: the host lowercased without `www.` or its port, then the path with the same segment encoding as
routing, trailing slashes dropped, **case kept** and no slash added. The page key is not the routing
path: `/News/` and `/news/` can resolve to the same fragment and still get different cards. The query
string and the hash are ignored, so `?r=123` does not change the pick. There is no randomness: with
the same pool, the same page always gets the same card. When the pool changes, because a card is
activated, archived or made eligible, a page may get another card.

The answer is a no-fill (`204`) when the pool is empty, or when the stored content of the chosen card
cannot be served. doubleshift never falls back to a card eligible elsewhere.

## No cache

Every answer of the fragment endpoint carries `Cache-Control: private, no-store`: the card, the
no-fill, and the errors. doubleshift keeps no response cache and no memory of your key between calls:
each call reads your current setup.

So these changes apply on the next call, with no change at your edge:

* pausing or resuming a fragment, or changing a routing rule or the site default;
* activating, archiving or reactivating a card, or changing its eligibility;
* revoking an API key.

Two need a redeploy at your edge: a new or rotated key, stored in its secret, and a page outside your
Worker's [`scope`](https://docs.shftd2.com/api/edge-library#scope).

The response of your own page to the agent is yours to cache or not. The rules your edge must keep
for it are in [The page response: cache contract](https://docs.shftd2.com/integrate.md#the-page-response-cache-contract).

## Where the card lands

The card is worth something only if the agent reads it, and text extractors tend to keep the article
and drop what surrounds it.

* The card goes **right before the article content**, intact: immediately before the article
  element, or first in `<main>`. Never inside the article, never at the end of the page.
* One line inside the article, its **first paragraph**, names the brand when a card is served:
  `Featured advertiser on this page: <brand>.` It keeps the disclosure in the text an extractor keeps.
* When the edge cannot find that spot, it serves the page without a card. It never puts the card
  somewhere else instead.

How each edge applies this is in [Where the card must land](https://docs.shftd2.com/integrate.md#where-the-card-must-land).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.