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

# redirectTapSource

> A tap source that reads the tap the redirect landed on this page. Runs before every other source: a tap in the URL is already in hand.

```ts theme={null}
redirectTapSource(options?: RedirectTapSourceOptions): TapSource

const REDIRECT_TAP_SOURCE_PRIORITY = 20
```

The redirect is the primary source on every platform: iOS has no in-page scanning, and on Android it is what the in-page scan falls back to. It runs at priority `20`, above the Web NFC scanner (`0`) and the manual source (`-10`), so a page opened by a tap resolves from its own URL before any scan starts.

Two landing shapes parse into one tap:

* **The page is the chip URL itself** - an Endstate-hosted page at `/verify/{chip_id}?e=` or `/u/{chip_id}?e=`.
* **A page you host behind an Endstate redirect** - it receives `endstate_pathId` (the chip id) and `endstate_e` as query parameters on its own URL. `endstate_chip_id` is accepted as an alias for the id, and `endstate_c` is forwarded when present.

Validation of the chip id and credential is delegated to the core parser, so this package and `@endstate-sdk/core` can never disagree about what a tap looks like.

<Warning>
  The hosted redirect records the tap in transit today, so verifying its
  forwarded values returns `chip.already_scanned`. Only the direct chip-URL
  shape currently supports `verify()`.
</Warning>

## Example

```ts theme={null}
import { EndstatePublicClient } from "@endstate-sdk/core";
import { redirectTapSource } from "@endstate-sdk/web";

const client = new EndstatePublicClient({
  publishableKey: "end_pk_live_...",
  tapSources: [redirectTapSource()],
});

const tap = await client.captureTap({ only: ["redirect"] });
if (tap) await client.verify(tap);
```

Pass `url` to read from somewhere other than the current page - a router-held location, or a fixture in a test:

```ts theme={null}
redirectTapSource({ url: () => router.currentUrl });
```

## Parameters

<ParamField body="options" type="RedirectTapSourceOptions">
  Optional configuration.
</ParamField>

<ParamField body="options.url" type="() => string">
  Where the landing URL is read from. Defaults to the current page
  (`window.location.href`, or an empty string when there is no `window`).
</ParamField>

## Returns

<ResponseField name="TapSource" type="object" required>
  A source named `redirect` with priority `REDIRECT_TAP_SOURCE_PRIORITY` (`20`).
  Its `isAvailable()` reports whether the current URL parses to a tap;
  `capture()` returns the parsed `TapResult`, or `null` when the URL carries no
  tap.
</ResponseField>

<ResponseField name="REDIRECT_TAP_SOURCE_PRIORITY" type="number" required>
  The source's priority, `20`. Exported for interfaces that order or compare
  sources themselves.
</ResponseField>
