# Preview source evidence

Resolve a citation to its source and check whether the quoted passage can be found.

Documentation index: https://webcite.co/llms.txt
Canonical page: https://webcite.co/api-docs/source-preview
API origin: https://api.webcite.co
Authentication: x-api-key header. Keep keys on your server.

## When to use it

For a web page, send `url`. For a file, send `asset_id` with a 1-based `page`, or a spreadsheet `cell` and optional `full`. For immutable evidence, send `source_version_id`, `representation_id`, and `source_unit_id` together. IDs must belong to the authenticated account.

A `reflowed` match uses a prepared OCR reading and remains subject to review. Preserve the original `matched_text` and the rescue provenance. See [evidence and review](/api-docs/evidence).

## Request

POST /api/v1/citations/source-preview

1 credit.

### curl

```curl
curl --fail-with-body -X POST 'https://api.webcite.co/api/v1/citations/source-preview' \
  -H "x-api-key: $WEBCITE_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
  "url": "https://www.toureiffel.paris/en/the-monument/key-figures",
  "quote": "330 meters"
}'
```

### Node.js

```javascript
const response = await fetch("https://api.webcite.co/api/v1/citations/source-preview", {
  method: "POST",
  headers: {
    "x-api-key": process.env.WEBCITE_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "url": "https://www.toureiffel.paris/en/the-monument/key-figures",
  "quote": "330 meters"
}),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
console.log(await response.json());
```

### python

```python
import os
import json
import requests

payload = json.loads("{\n  \"url\": \"https://www.toureiffel.paris/en/the-monument/key-figures\",\n  \"quote\": \"330 meters\"\n}")
response = requests.post(
    "https://api.webcite.co/api/v1/citations/source-preview",
    headers={"x-api-key": os.environ["WEBCITE_API_KEY"]},
    json=payload,
    timeout=(10, 300),
)
response.raise_for_status()
print(response.json())
```

## Response

Returns a source preview and binding information. Check binding.grounded, binding.method, and the matched passage before presenting the quote as source-backed.

## Errors

For 400, check the request fields and source identifiers. For 401, check your API key. For 429, wait for the retry interval. See the errors guide before retrying a billable request.

## OpenAPI operation

```json
{
  "path": "/api/v1/citations/source-preview",
  "method": "POST",
  "operation": {
    "description": "Resolve a citation back to its exact source and render it, so you can show the evidence behind a claim.\n\n- **Web sources** (`url`): returns a text-fragment deep link (`url#:~:text=quote`) that scrolls a browser to the quote.\n- **Document sources** (`asset_id`, from POST /upload): returns the cited page's extracted text and a `asset_url#page=N` deep link. Spreadsheets return the sheet grid.\n\nEvery preview includes a **bindBack** result: whether the cited quote is actually present in the source (`grounded`) and how it matched (`exact`, `normalized`, `fuzzy`, `reflowed`, or `unbound`). A `reflowed` match used a derived OCR reading and always requires review. A citation that cannot be bound back is never reported as grounded.\n\n**Cost: 1 credit.** No LLM calls, but a web preview fetches the source URL, so this endpoint is subject to your plan's rate limits.",
    "operationId": "ApiV1Controller_sourcePreview",
    "parameters": [],
    "requestBody": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/SourcePreviewRequestDto"
          }
        }
      },
      "required": true
    },
    "responses": {
      "200": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/SourcePreviewResponseDto"
            }
          }
        },
        "description": "Source preview with bindBack verification"
      },
      "400": {
        "description": "Provide a web url or an asset_id"
      },
      "401": {
        "description": "Unauthorized - API key required"
      },
      "429": {
        "description": "Rate limit exceeded"
      }
    },
    "security": [
      {
        "x-api-key": []
      },
      {
        "bearer": []
      }
    ],
    "summary": "Preview a citation source",
    "tags": [
      "Public API"
    ]
  },
  "schemas": {
    "SourcePreviewRequestDto": {
      "properties": {
        "asset_id": {
          "description": "Uploaded asset ID to preview (from POST /upload). Provide this OR url. Also accepts an \"asset://<id>\" citation url.",
          "example": "123e4567-e89b-12d3-a456-426614174000",
          "type": "string"
        },
        "cell": {
          "description": "A1 cell anchor for a legacy spreadsheet preview.",
          "type": "string"
        },
        "full": {
          "description": "Return the capped full sheet instead of a cell window.",
          "type": "boolean"
        },
        "highlight_terms": {
          "description": "Terms to highlight in the preview.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "page": {
          "default": 1,
          "description": "1-based page (PDF) or sheet index (spreadsheet) to preview.",
          "example": 3,
          "type": "number"
        },
        "quote": {
          "description": "The cited quote. It is bound back against the resolved source text; the response reports whether it was found (grounded) and how it matched.",
          "example": "the Eiffel Tower is 330 metres tall",
          "type": "string"
        },
        "representation_id": {
          "description": "Exact parser representation, never latest.",
          "type": "string"
        },
        "source_unit_id": {
          "description": "Exact unit within the immutable representation.",
          "type": "string"
        },
        "source_version_id": {
          "description": "Immutable source version. Requires representation_id and source_unit_id.",
          "type": "string"
        },
        "title": {
          "description": "Optional title for a web source.",
          "type": "string"
        },
        "url": {
          "description": "Web source URL to preview. Provide this OR asset_id. Returns a text-fragment deep link that scrolls to the quote.",
          "example": "https://en.wikipedia.org/wiki/Eiffel_Tower",
          "type": "string"
        }
      },
      "type": "object"
    },
    "SourcePreviewResponseDto": {
      "properties": {
        "anchor": {
          "type": "string"
        },
        "asset_id": {
          "description": "Asset ID (kind=page|grid).",
          "type": "string"
        },
        "binding": {
          "allOf": [
            {
              "$ref": "#/components/schemas/BindBackDto"
            }
          ],
          "description": "bindBack result — whether the quote is grounded in the source."
        },
        "cells": {
          "description": "Bounded rows of cells with A1 refs, values and anchor flags.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "deep_link": {
          "description": "Deep link to the source at the cited location: url#:~:text=quote for web, asset_url#page=N for documents.",
          "type": "string"
        },
        "highlight_terms": {
          "description": "Highlight terms.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "image_base64": {
          "type": "string"
        },
        "judgment": {
          "type": "object"
        },
        "kind": {
          "description": "Preview shape.",
          "enum": [
            "web",
            "page",
            "grid",
            "unit",
            "image"
          ],
          "type": "string"
        },
        "locator": {
          "type": "object"
        },
        "mime_type": {
          "enum": [
            "application/pdf"
          ],
          "type": "string"
        },
        "page": {
          "description": "Page/sheet number (kind=page|grid).",
          "type": "number"
        },
        "quote": {
          "description": "The cited quote.",
          "type": "string"
        },
        "representation_id": {
          "type": "string"
        },
        "sheet": {
          "description": "Sheet name (kind=grid).",
          "type": "string"
        },
        "source_unit_id": {
          "type": "string"
        },
        "source_version_id": {
          "type": "string"
        },
        "state": {
          "type": "object"
        },
        "text": {
          "description": "Resolved source text (kind=page|grid).",
          "type": "string"
        },
        "title": {
          "description": "Web source title (kind=web).",
          "type": "string"
        },
        "url": {
          "description": "Web source URL (kind=web).",
          "type": "string"
        }
      },
      "required": [
        "kind",
        "deep_link",
        "binding"
      ],
      "type": "object"
    },
    "BindBackDto": {
      "properties": {
        "grounded": {
          "description": "True when the quote was found in the resolved source.",
          "type": "boolean"
        },
        "matched_quote": {
          "description": "The matched substring, when grounded verbatim.",
          "type": "string"
        },
        "matched_text": {
          "description": "The best-matching passage found in the source — present even when unbound, so a reviewer sees the closest evidence.",
          "type": "string"
        },
        "method": {
          "description": "How the quote matched: exact/normalized substring, fuzzy passage match, reflowed OCR reading, or unbound.",
          "enum": [
            "exact",
            "normalized",
            "fuzzy",
            "reflowed",
            "unbound"
          ],
          "type": "string"
        },
        "reading": {
          "description": "Derived body reading with page furniture removed; absent for stored text.",
          "enum": [
            "body"
          ],
          "type": "string"
        },
        "rescue": {
          "description": "OCR rescue outcome: attempted=false with code/reason, attempted=true and rescued=false (optionally ambiguous), or rescued=true with transformations, raw dropped lines and retained spans. Unknown or unattempted is never a failed rescue.",
          "oneOf": [
            {
              "properties": {
                "attempted": {
                  "enum": [
                    false
                  ],
                  "type": "boolean"
                },
                "code": {
                  "enum": [
                    "not_ocr",
                    "labels_not_available",
                    "judge_unavailable",
                    "not_prepared",
                    "disabled",
                    "resource_limit"
                  ],
                  "type": "string"
                },
                "reason": {
                  "type": "string"
                }
              },
              "required": [
                "attempted",
                "code",
                "reason"
              ],
              "type": "object"
            },
            {
              "properties": {
                "ambiguous": {
                  "enum": [
                    true
                  ],
                  "type": "boolean"
                },
                "attempted": {
                  "enum": [
                    true
                  ],
                  "type": "boolean"
                },
                "rescued": {
                  "enum": [
                    false
                  ],
                  "type": "boolean"
                }
              },
              "required": [
                "attempted",
                "rescued"
              ],
              "type": "object"
            },
            {
              "properties": {
                "attempted": {
                  "enum": [
                    true
                  ],
                  "type": "boolean"
                },
                "basis": {
                  "enum": [
                    "code",
                    "measured"
                  ],
                  "type": "string"
                },
                "calibrationKey": {
                  "type": "string"
                },
                "decidedAt": {
                  "format": "date-time",
                  "type": "string"
                },
                "droppedLines": {
                  "items": {
                    "type": "string"
                  },
                  "type": "array"
                },
                "model": {
                  "nullable": true,
                  "type": "string"
                },
                "reading": {
                  "description": "Derived matching text; display the raw preview text instead.",
                  "type": "string"
                },
                "rescued": {
                  "enum": [
                    true
                  ],
                  "type": "boolean"
                },
                "retainedSpans": {
                  "items": {
                    "properties": {
                      "fromLine": {
                        "type": "integer"
                      },
                      "page": {
                        "type": "integer"
                      },
                      "toLine": {
                        "type": "integer"
                      }
                    },
                    "required": [
                      "page",
                      "fromLine",
                      "toLine"
                    ],
                    "type": "object"
                  },
                  "type": "array"
                },
                "transformations": {
                  "items": {
                    "properties": {
                      "afterLine": {
                        "type": "integer"
                      },
                      "atLine": {
                        "type": "integer"
                      },
                      "kind": {
                        "enum": [
                          "dehyphenate",
                          "join",
                          "drop"
                        ],
                        "type": "string"
                      },
                      "line": {
                        "type": "string"
                      },
                      "source": {
                        "enum": [
                          "element_label",
                          "repetition",
                          "page_number",
                          "margin_band"
                        ],
                        "type": "string"
                      }
                    },
                    "required": [
                      "kind"
                    ],
                    "type": "object"
                  },
                  "type": "array"
                }
              },
              "required": [
                "attempted",
                "rescued",
                "reading",
                "transformations",
                "droppedLines",
                "retainedSpans",
                "calibrationKey",
                "basis",
                "model",
                "decidedAt"
              ],
              "type": "object"
            }
          ]
        },
        "score": {
          "description": "Similarity of the best match, 0..1.",
          "type": "number"
        }
      },
      "required": [
        "grounded",
        "method"
      ],
      "type": "object"
    }
  }
}
```
