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

# Build a keyless citation demo

> Give a coding assistant one prompt to build a page with clickable source attributions.

Paste this prompt into Claude or another coding assistant. It describes a small page that calls TokenPath directly. The assistant writes the initial answer; TokenPath connects that answer to its source text.

## Copy this prompt

```text theme={null}
Build a self-contained HTML page with editable source text, question, and
answer fields, a “Find sources” button, and clickable citations. Use this
initial source: “The Oregon Duck wears a green and yellow costume.”
Question: “What colors does the Oregon Duck wear?”
Answer: “The Oregon Duck wears green and yellow.”

On button click, POST JSON to https://api.tokenpath.ai/v1/attributions:
{ "document": sourceText, "question": questionText,
  "answer": answerText, "offset_encoding": "utf-16" }
Use Content-Type: application/json and credentials: "omit".
Do not send an Authorization header. Do not call a generation endpoint.

The response is { "spans": [{ "answer": { "start": 0, "end": 5,
"text": "..." }, "source": { "start": 10, "end": 15,
"text": "...", "confidence": 0.8 } }], "offset_encoding": "utf-16" }.
The offsets in this example are illustrative; use the real response.
Each range is half-open and works with JavaScript String.slice.

Show the exact submitted answer and a citation button for each returned
answer phrase. Clicking a citation highlights the returned source range
in the exact submitted document. Do not trim or rewrite submitted strings
before displaying their ranges. Render text safely with textContent.
If spans is empty or source is null, explain that no source was found;
never fabricate citation results. Confidence is attribution strength,
not a correctness score.

Disable the button while a request is running and invalidate results when
inputs change. Only send on button click. Show readable server errors:
413 means reduce input size; 429 means wait for Retry-After before another
attempt; 401 means keyless access is currently unavailable. Do not retry
automatically. Keep source text within 20,000 Unicode characters and the
question and answer within 2,000 each. Add a small “Attributions by
TokenPath” link to https://tokenpath.ai.

If the embedded preview cannot make external requests, provide the HTML
file to run in a regular browser. Report network failures honestly.
```

The page needs external network access. An embedded artifact may impose restrictions independently of TokenPath's browser-access policy. You can also run the generated HTML in a regular browser. No provider key is needed for the initial sample or for an answer you paste yourself.

## Browser request

```javascript theme={null}
async function findSources(document, question, answer) {
  const response = await fetch("https://api.tokenpath.ai/v1/attributions", {
    method: "POST",
    credentials: "omit",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ document, question, answer, offset_encoding: "utf-16" }),
  });
  const result = await response.json();
  if (!response.ok) {
    const retryAfter = response.headers.get("Retry-After");
    throw new Error(
      (result.error?.message ?? `Request failed (${response.status})`) +
      (retryAfter ? ` Retry after ${retryAfter} seconds.` : ""),
    );
  }
  return result;
}
```

See [keyless limits](/api-reference/post-attributions#keyless-access) for the current input and shared capacity limits, and [Inline Citations](/cookbooks/inline-citations) for more rendering examples.
