All endpoints

DocsAPITrackers

GET/sites/{siteId}/trackers

Read the tracker inventory

Every tracker our scans and the connected Tag Manager container found, grouped by vendor, with our category for each tag and the cookies each vendor set.

Auth header

Authorization: Bearer tsk_live_…

The key needstrackers:read

Parameters

  • siteIdstringin pathrequired

    The site id, from GET /v1/sites.

Example request

curl "https://app.tagsentry.ai/api/v1/sites/3f6c1b8e-2d4a-4c7e-9a51-0b8f2e6d7c10/trackers" \  -H "Authorization: Bearer tsk_live_…"

Response 200

  • dataarray of objectrequired
  • data[].vendorNamestringrequired
  • data[].vendorHoststring | nullrequired
  • data[].vendorIsRecognisedbooleanrequired
  • data[].vendorBestGuessobject | nullrequired

    Our best guess at who an unrecognised host is, from its address alone; vendorName is then this vendor. Nobody has confirmed it. Null when the host is recognised or we have no guess.

  • data[].vendorBestGuess.vendorstringrequired
  • data[].vendorBestGuess.productstringrequired
  • data[].vendorBestGuess.categorystringrequired

    One of analytics, advertising, functional, necessary, unknown

  • data[].vendorBestGuess.whatItDoesstringrequired
  • data[].vendorBestGuess.confidencenumberrequired
  • data[].sourcesarray of stringrequired
  • data[].unmanagedCountintegerrequired

    Tags seen on the page that no Tag Manager container we can read fires.

  • data[].needsReviewCountintegerrequired

    No human has confirmed these. We still decided a category where we could.

  • data[].lastSeenAtstringrequired

    ISO-8601 timestamp, UTC.

  • data[].tagsarray of objectrequired
  • data[].tags[].idstringrequired
  • data[].tags[].displayNamestringrequired
  • data[].tags[].sourcestringrequired

    One of gtm_container, live_scan, both

  • data[].tags[].gtmContainerPublicIdstring | nullrequired
  • data[].tags[].gtmTagIdstring | nullrequired
  • data[].tags[].gtmTagTypestring | nullrequired
  • data[].tags[].isUnmanagedbooleanrequired
  • data[].tags[].needsReviewbooleanrequired
  • data[].tags[].categorystring | nullrequired

    Our answer, or null when neither source has one.

  • data[].tags[].categoryBasisstring | nullrequired

    One of vendor_table, classifier

  • data[].tags[].firstSeenAtstringrequired

    ISO-8601 timestamp, UTC.

  • data[].tags[].lastSeenAtstringrequired

    ISO-8601 timestamp, UTC.

  • data[].cookiesarray of objectrequired
  • data[].cookies[].namestringrequired
  • data[].cookies[].domainstringrequired
  • data[].cookies[].partystringrequired

    One of first, third

  • data[].cookies[].expirystring | number | nullrequired

    Seconds, 'session', or null when unknown.

  • data[].cookies[].setByobject | nullrequired
  • data[].cookies[].setBy.viastringrequired

    One of http, script, domain

  • data[].cookies[].setBy.hoststring | nullrequired
  • limitintegerrequired

    The row cap applied to the underlying read.

  • truncatedbooleanrequired

    True when the read came back at its cap. When true, this page is NOT the whole answer -- narrow the window. The tracker inventory is read whole; truncated is always false here.

  • truncationHintstringoptional

Example response

{  "data": [    {      "vendorName": "Google Analytics",      "vendorHost": "www.google-analytics.com",      "vendorIsRecognised": false,      "vendorBestGuess": {        "vendor": "…",        "product": "…",        "category": "analytics",        "whatItDoes": "…",        "confidence": 0      },      "sources": [        "gtm_container"      ],      "unmanagedCount": 0,      "needsReviewCount": 0,      "lastSeenAt": "2026-09-26T14:02:00.000Z",      "tags": [        {          "id": "3f6c1b8e-2d4a-4c7e-9a51-0b8f2e6d7c10",          "displayName": "Silverpine Supply",          "source": "gtm_container",          "gtmContainerPublicId": "GTM-ABC1234",          "gtmTagId": "12",          "gtmTagType": "…",          "isUnmanaged": false,          "needsReview": false,          "category": "analytics",          "categoryBasis": "vendor_table",          "firstSeenAt": "2026-09-26T14:02:00.000Z",          "lastSeenAt": "2026-09-26T14:02:00.000Z"        }      ],      "cookies": [        {          "name": "_ga",          "domain": "silverpine.example",          "party": "first",          "expiry": "session",          "setBy": {            "via": "http",            "host": "www.google-analytics.com"          }        }      ]    }  ],  "limit": 50,  "truncated": false,  "truncationHint": "…"}
More about this endpoint

category is our answer: from our sourced vendor table where it has one, else from our classifier. needsReview means no human has confirmed it, not that nobody decided.

Errors401 · 403 · 404 · 429 · 500
  • 401Missing, malformed, unknown, revoked or expired API key. These are deliberately indistinguishable in the response -- distinguishing them would confirm to a caller that a token was once real.
  • 403The key authenticated but does not carry the scope(s) this operation requires, or (`domain_not_verified`) the site's domain is not verified, so its consent records are not released.
  • 404No such resource on this account. A site id belonging to a DIFFERENT account answers 404, never 403 -- a 403 would confirm the id exists somewhere.
  • 429A rate limit or quota was exceeded. The body names WHICH one.
  • 500Something failed on our side. The requestId in the body is what to quote.

Every error has the same body: { error: { code, message, requestId } }.

From the OpenAPI document, version 2026-08-26. Raw OpenAPI