Source: https://seerepo.com/docs/api-found
Markdown source: https://seerepo.com/docs/api-found.md
Description: How search engines and AI see each public page, read from the code, with proof.

# Get the visibility

`GET https://seerepo.com/api/v1/repos/:repo/found`

Returns Pages outside as it reads in the app: each public page with its signals (title, description, canonical, image, card, noindex, sitemap entry, structured data, versions by language, main heading, and what robots.txt tells Googlebot, OAI-SearchBot and GPTBot), each with an honest label and the file and line that prove it. The labels promise no indexing and no traffic: BLOCK (something stops a search engine), WARN (something worth adding), UNKNOWN (the code can't tell), INFO (said without judging) and PASS.

## Request

| Parameter | Where | Description |
|---|---|---|
| `repo` | path | The repo's id, or owner/name with %2F. |

```sh
curl "https://seerepo.com/api/v1/repos/6ad79fd8e89233277ded17c9/found" \
  -H "Authorization: Bearer $SEEREPO_KEY"
```

## Response

| Field | Type | Description |
|---|---|---|
| `data.repo` | object | The repo: its id and its name. |
| `data.summary` | object\|null | How many public pages, how many more weren't judged because their door wasn't seen (`unseen`), how many need work (a WARN or a BLOCK), how many were read, how many are blocked, the pages opened by their link and the private ones by who gets in. And `findable`, Visibilidad's ring in the app: of the public pages that want to be on Google, how many can be found (`n`) of how many (`of`), and how many you hid on purpose (`hidden`), which don't count; null if none wants to be. Null until a scan reads them. |
| `data.site` | object | Each app's files for machines: where robots comes from, the sitemaps it announces, its sitemaps and its `llms.txt`. |
| `data.pages[]` | object | Each public page: its path, route, name, who gets in, and its `signals[]`, each with its `key`, `status`, `label`, `proof` (its path, line and `url` on GitHub at the scanned commit) and, when there is one, its fixed `value` and its `why`. |
| `data.withLink[]` | object | The pages opened by what their link carries, apart: they shouldn't be in search. |
| `data.live` | object\|null | What the published site answered on the project's last day it was asked (once a day, only when the repo has a website or a GitHub homepage): the day, where it was asked, how many public pages were measured, blocked and incomplete, and the site's robots.txt and sitemap; or why nothing was asked (`no-address`, `free`, `demo`). Each page then carries `live` (where it was asked and how the whole page answered, or why it wasn't; `redirected` when the site sent it to another page, and then its signals aren't crossed), and each signal with a pair on the site carries `live` (the auditor's status, what it says and its evidence) and `agrees` (whether the code and the site say the same, when both could tell). Null until the first day, and on the free look. |
| `data.search` | object\|null | What Google Search Console says, when the project is connected to it (null otherwise, and on a free repo): the window (`from`, `to`), its `clicks`, `impressions` and `pages`, and how many pages were inspected, indexed and not; or why it wasn't read (`reason`). Each page then has its `search`: its clicks, impressions, CTR, position and, once inspected, Google's index verdict. |
| `data.rules` | object | The version of the rules its last scan judged with, the current one, and each change with its date: a figure that moves because a rule changed says so. |
| `data.visits` | object\|null | What DataFast counts on the site in its last 30 days, when the project is connected to it and it has been read (null otherwise): the window (`from`, `to`), the `total`, each day in `series[]` (`d`, `n`), each screen that isn't a public page in `screens[]` (`path`, `n`) and the addresses that are no screen of the code in `other[]` (`route`, `n`). A visit is one person on one screen in one day. Each page in `data.pages[]` then brings its own in `visits.n`. |
| `data.reads` | object | Whether the visits were read: `visits` is `read`, `unread` (connected and not read yet) or `na` (not connected). |
| `data.locked` | boolean | A repo on the free look: only how many public pages there are and how many need work, as in the app. |

### Example

```json
{
  "status": "success",
  "data": {
    "repo": { "id": "6ad79fd8e89233277ded17c9", "name": "shop" },
    "summary": { "public": 12, "unseen": 0, "needWork": 4, "checked": 12, "blocked": 1, "withLink": 1, "private": { "signed-in": 8, "member": 0, "owner": 1 }, "findable": { "n": 10, "of": 11, "hidden": 1 } },
    "site": [{ "app": "app", "robots": { "path": "app/robots.ts", "computed": false }, "announced": [{ "url": "https://shop.example/sitemap.xml", "line": 8 }], "sitemaps": ["app/sitemap.ts"], "llms": null }],
    "pages": [
      {
        "path": "app/checkout/page.tsx",
        "route": "/checkout",
        "name": "Pay",
        "who": "anyone",
        "read": true,
        "signals": [{ "key": "title", "status": "ok", "label": "PASS", "proof": { "path": "app/checkout/page.tsx", "line": 3 }, "value": "Pay | Shop", "by": "rule" }]
      }
    ],
    "withLink": [],
    "live": { "d": "2026-10-21", "at": "2026-10-21T15:00:00.000Z", "origin": "https://shop.example", "from": "website", "pages": 12, "measured": 12, "blocked": 0, "incomplete": 1, "site": [] },
    "rules": { "version": 1, "current": 1, "changes": [{ "folder": "found", "version": 1, "d": "2026-10-21", "id": "found-1", "what": "Each public page's search signals read from the code, labeled as foundvia-discovery labels them" }] },
    "locked": false,
    "visits": null,
    "reads": { "visits": "na" }
  }
}
```

## Authentication

An API key as `Authorization: Bearer sr_…`. See [Authentication](/docs/api#authentication).

## Errors

The ones every endpoint has (401, 404, 429), see [Errors](/docs/api#errors).
