# Install databob with an AI agent (/docs/agents) An agent can read these docs without scraping HTML. | Resource | URL | | ---------------------- | ------------------------------------------------------------------------------------------- | | Index | [https://docs.databob.dev/llms.txt](https://docs.databob.dev/llms.txt) | | Every page in one file | [https://docs.databob.dev/llms-full.txt](https://docs.databob.dev/llms-full.txt) | | One page | Append `.md`. [Quickstart](/docs/quickstart.md) is the Markdown for this site's quickstart. | On any page, **Copy page as Markdown** copies that `.md` file. **Open** includes **Open in ChatGPT**, **Open in Claude**, and **Open in Cursor**. Those links ask the model to read the public page URL. ## What the agent should install [#what-the-agent-should-install] There is no package to add. Do not invent an SDK, a `data-content` attribute, or an EU ingest host. The install is the script tag from [Quickstart](/docs/quickstart). ```html title="index.html" ``` The human still has to sign up at [databob.dev/sign-up](https://databob.dev/sign-up), create the site, and paste the real `dbw_` write key. The agent should not embed a guessed key. `YOUR_SITE_ID` is the project id from the dashboard, not a domain. After the tag is on an allowed origin, a reload sends `POST https://us-ingest.databob.dev/v1/collect`. A stored pageview is `202` with `{ "stored": true }`. To read counts, the human creates a `dbk_live_` or `dbk_test_` key under API keys. The agent calls: ```sh title="content-report.sh" curl -sS \ -H "Authorization: Bearer dbk_live_REPLACE" \ "https://api.databob.dev/v1/reports/content?project_id=PROJECT_ID&period=7d&content_id=post_123" ``` Branch on the `error` field. The codes are `bad_request`, `unauthorized`, `forbidden`, `not_found`, `rate_limited`, and `unavailable`. Details are on [Rate limits and errors](/docs/rate-limits). Official SDKs, EU ingest, and billing are not part of this release. If a task needs one of those, say it is not available instead of scaffolding it. # API keys (/docs/api-keys) Data API keys are not the install write key. The write key starts with `dbw_` and is only for `POST /v1/collect`. A data API key starts with `dbk_live_` or `dbk_test_` and is only for the read API. A legacy `dbr_` read key is not accepted. The dashboard itself still uses your Clerk session. Create keys at [databob.dev/dashboard/api-keys](https://databob.dev/dashboard/api-keys). ## Who can do what [#who-can-do-what] An owner or admin creates, names, lists, and revokes keys for one explicit org. A member of that org can list keys. Members do not see who created a key. A key is read-only. Scope is one site, or every site in the org. There is no write scope. The full secret is shown once. Convex stores an HMAC-SHA256 of the secret, not the secret. The prefix is a label. Authorization is the HMAC. An org can have 25 active keys. Revoking a key frees a slot. `lastUsedAt` is updated at most once a minute on a request that is allowed through. ## Which prefix you get [#which-prefix-you-get] | Deployment | New keys | | ----------------------------- | ------------------------------------------------- | | Production (`savory-yak-367`) | `dbk_live_`, even if the mode is unset or `test` | | Anywhere else | `dbk_test_`, unless `DATA_API_KEY_MODE` is `live` | Set `DATA_API_KEY_MODE` to `live` on production anyway. The pepper `DATA_API_KEY_PEPPER` has to be set on the Convex deployment before a key can be created. It is not trimmed. Without it, key creation fails and the read routes return `500` with `{ "error": "unavailable" }`. ## Send it [#send-it] ```http title="Authorization" Authorization: Bearer dbk_live_REPLACE ``` A missing, unknown, or revoked key is `401`. The install write key in that header is `401` as well. There is no official client library yet. Call `https://api.databob.dev` with the header above. The machine-readable contract is `docs/data-api.openapi.yaml`, and `info.version` is `1`. Pepper rotation, for operators: copy the current pepper into `DATA_API_KEY_PEPPER_PREVIOUS` without trimming either value, set a new `DATA_API_KEY_PEPPER`, and deploy. Keys hashed with the previous pepper stay valid while that variable is set and `hashVersion` is still `1`. Unset the previous pepper when those older keys should stop working. Do not bump the hash version for a pepper rotation. That invalidates every key. # Changelog (/docs/changelog) ## 2026-10-26 [#2026-10-26] First published docs for the current product. * Script tag at `https://databob.dev/databob.js`, collect at `https://us-ingest.databob.dev/v1/collect`, write keys `dbw_`. * Consent banner with essential cookieless analytics and optional enhanced analytics. Global Privacy Control and Do Not Track opt out of the enhanced tier. Hosted privacy choices at `/c/`. * Data API version 1: `GET /v1/reports/content` and `GET /v1/snapshots/content`. Keys `dbk_live_` and `dbk_test_`. 120 requests per key and 600 per org each minute. * Dashboard Overview, Consent, API keys, and Settings. Realtime, Pages, and Sources are still empty. * Agent entry points: `/llms.txt`, `/llms-full.txt`, and `.md` for every page. Not in this release: official SDKs, EU ingest, and billing. # Consent and banner (/docs/consent) Essential cookieless analytics is always on. The banner is shown only when enhanced analytics is enabled for the project, and only for a visitor who still needs to choose. Edit it at [Dashboard, Consent](https://databob.dev/dashboard/settings). Accept, Reject, and Customize use one button style. The enhanced category starts unchecked. ## Categories [#categories] | Category | Required | What it covers | | ------------------------------ | -------------------- | ------------------------------------------------------------------------------- | | Essential cookieless analytics | yes, always on | Path, content id, country, and device class. No cookie and no personal data. | | Enhanced analytics | no, starts unchecked | Referring site, `utm_source`, `utm_medium`, `utm_campaign`, and the goal event. | The default enhanced label is `Enhanced analytics`. The default banner text says essential cookieless analytics is always on and that enhanced analytics stays off unless the visitor accepts it. Leave the text empty in the dashboard to keep that default. There is no advertising category in the tracker. An outside consent adapter is not built. ## Where the banner shows [#where-the-banner-shows] Two regions are saved on the project. **EU, EEA, UK, Switzerland, and Canada** (`eu_uk_ca`). This is the default. The country codes are Austria, Belgium, Bulgaria, Croatia, Cyprus, Czechia, Denmark, Estonia, Finland, France, Germany, Greece, Hungary, Ireland, Italy, Latvia, Lithuania, Luxembourg, Malta, the Netherlands, Poland, Portugal, Romania, Slovakia, Slovenia, Spain, Sweden, Iceland, Liechtenstein, Norway, the United Kingdom, Canada, and Switzerland. An unknown country is asked. Everyone else is not asked and stays cookieless. California visitors are not prompted and stay cookieless. They can still open Privacy choices. **Everywhere.** Every visitor sees the banner until they choose, except a browser that sends Global Privacy Control or Do Not Track. ## Global Privacy Control [#global-privacy-control] Global Privacy Control is honored everywhere, including when the region is Everywhere. The banner stays hidden and enhanced analytics stays off. The same is true for Do Not Track (`DNT: 1` or `navigator.doNotTrack === "1"`). The tracker treats `navigator.globalPrivacyControl === true` as an opt-out before it paints the banner. The Worker treats `Sec-GPC: 1` and `DNT: 1` as an opt-out even if the body says analytics was granted. A stored choice is written as denied for the current consent version. ## What asks again [#what-asks-again] The choice is `localStorage` on the customer site, under `databob.consent.`: ```json title="localStorage" { "v": 1, "enhanced": false, "source": "databob" } ``` These edits bump the consent version and ask again: * Banner text * Privacy policy URL * Enhanced label * Region * Enhanced analytics on or off Colors and position do not bump the version. Default colors are `#111111`, `#f4f4f5`, and `#f4f4f5`. A banner that still has those defaults follows the visitor's light or dark setting. Custom colors do not. Position is bottom or top. The privacy policy link is rendered only when the URL is `https` and has no username or password. Anything else is published as a blank policy URL. ## Hosted privacy choices [#hosted-privacy-choices] Privacy choices opens `https://databob.dev/c/`. The page uses the same neutral theme as the app, with its own light and dark toggle, and it does not load the tracker. The page cannot be framed (`Content-Security-Policy: frame-ancestors 'none'` and `X-Frame-Options: DENY`) and it sends `Referrer-Policy: no-referrer`. After it has read the nonce and the return URL, it removes both from the address bar. Before the tracker opens that page, it stores a single-use nonce in `sessionStorage` under `databob.nonce.`. The page echoes the nonce in a `#databob=` hash on an allowed return URL, or in a `postMessage` when it was opened as a popup. The message type is `databob-consent`. The tracker accepts the choice only when the nonce matches, then deletes the nonce. A hash or message without that nonce does not grant enhanced analytics. The page never posts to `*`. The enhanced box starts from the stored choice for the current version, or unchecked. A `?enhanced=1` link does not pre-tick it. If the page cannot see an allowed return origin, it says the choice was saved in that browser and to choose again from the site. A consent beacon is a separate point: action `granted`, `denied`, or `changed`, category `enhanced`, the version, and `source`. It has no path, country, address, or visitor id. The dashboard Consent page shows granted, denied, and changed counts for 7 days and 28 days from the daily snapshot. It does not store one row per visitor. Consent settings take up to about a minute to apply. # Dashboard guide (/docs/dashboard) The signed-in app is [databob.dev/dashboard](https://databob.dev/dashboard). The theme defaults to dark. Cmd-K or Ctrl-K opens the command menu for pages, sites, and the theme. The sidebar is Overview, Realtime, Pages, Sources, Consent, API keys, and Settings. Docs in that sidebar opens this site. ## Overview [#overview] Overview shows the org name, your name, your email, and the plan. The plan label is Free. Billing is not turned on. **New project** asks for a project name, an `https` site URL, and an optional goal event name. The site URL allows that host and its `www` counterpart. Creating a project reveals the `dbw_` write key once. Copy it then. Rotating the write key revokes the old one immediately. The dashboard does not issue a `dbr_` read key. Each active project shows one install snippet. It uses `YOUR_WRITE_KEY` until a secret is on screen. The script URL is `https://databob.dev/databob.js` unless the deployment sets `NEXT_PUBLIC_DATABOB_SCRIPT_URL`. Collect defaults to `https://us-ingest.databob.dev/v1/collect`. ## Reports that are empty [#reports-that-are-empty] | Page | What you see | | -------- | -------------------------------------------------- | | Realtime | "This report is not available yet." No live chart. | | Pages | No page report. Content snapshots stay on the API. | | Sources | No referrer or campaign list. | Those screens are not a bug in the snippet. The content report is [the data API](/docs/data-api). ## Consent [#consent] [Consent](/docs/consent) is edited at `/dashboard/settings`. The page shows the hosted preferences path, the choice version, banner text, colors, position, privacy policy URL, the enhanced switch and label, and the region. It also shows granted, denied, and changed counts for 7 days and 28 days when a snapshot exists. ## API keys [#api-keys] [API keys](/docs/api-keys) live at `/dashboard/api-keys`. They are separate from the install write key. ## Settings [#settings] `/dashboard/account` shows the org, the plan, your name, your email, and the theme toggle. Dark is the default. The choice is stored in this browser. ## Account states [#account-states] If the Clerk webhook has not finished, the dashboard says it is creating the org and offers Retry. A removed user sees that the account was removed and is not recreated. # Data API (/docs/data-api) The public base URL is `https://api.databob.dev`. The same routes are Convex HTTP actions on the deployment site URL. Ingest stays on the Worker. A hit returns the stored snapshot. It does not query Analytics Engine. `info.version` is `1`. Every path is under `/v1`. A breaking change gets a new path prefix. Adding an optional JSON field is not a breaking change. Ignore unknown fields. Branch on `error`, not on `message`. `GET /v1/reports/content` reads the snapshot and records each content id so the daily rebuild will refresh it. `GET /v1/snapshots/content` reads the same snapshot and does not record a request. There are no other report types. ## Query [#query] | Parameter | Required | Values | | ------------- | -------------------------------- | ---------------------------------------------------------------------------- | | `period` | yes | `7d` or `28d` | | `content_id` | one of the two id parameters | A single content id. Do not combine with `content_ids`. | | `content_ids` | one of the two id parameters | Comma-separated. At most 20. | | `project_id` | when the key can read every site | A project id. A key limited to one site uses that site when this is omitted. | A different site in the same org is `403`. A missing project and a project in another org are both `404`. The script tag stores the pathname as the content id. Query with that path, for example `/pricing`, unless a collect body included `content_id`. The samples below use `post_123`, which is the id in the OpenAPI examples. ## Samples [#samples] ```sh title="reports.sh" curl -sS \ -H "Authorization: Bearer dbk_live_REPLACE" \ "https://api.databob.dev/v1/reports/content?project_id=PROJECT_ID&period=7d&content_id=post_123" ``` ```sh title="snapshots.sh" curl -sS \ -H "Authorization: Bearer dbk_test_REPLACE" \ "https://api.databob.dev/v1/snapshots/content?project_id=PROJECT_ID&period=28d&content_ids=post_123,post_456" ``` ```js title="report.js" {3} const response = await fetch( "https://api.databob.dev/v1/reports/content?project_id=PROJECT_ID&period=7d&content_id=post_123", { headers: { Authorization: "Bearer dbk_live_REPLACE" } }, ); const report = await response.json(); ``` ```python title="report.py" {5} import urllib.request request = urllib.request.Request( "https://api.databob.dev/v1/reports/content?project_id=PROJECT_ID&period=7d&content_id=post_123", headers={"Authorization": "Bearer dbk_live_REPLACE"}, ) with urllib.request.urlopen(request) as response: print(response.read().decode()) ``` ## Response [#response] ```json title="200.json" { "report": "content", "period": "7d", "items": [ { "id": "post_123", "views": 40, "previous_views": 12, "enough_data": true } ] } ``` `views` is the current window. `previous_views` is the window before it. `enough_data` is false when the current window was extrapolated from fewer than three unweighted rows. If no snapshot exists yet, the item is `views: 0`, `previous_views: 0`, `enough_data: false`. A batch larger than 20 is rejected. At most 20 items are returned. The rebuild runs daily at 04:00 UTC. Calling the reports route records the ids for that job. Calling the snapshots route does not. The interactive reference, with the auth header, code samples, and error bodies, is generated from the OpenAPI document: * [GET /v1/reports/content](/docs/api/getContentReport) * [GET /v1/snapshots/content](/docs/api/getContentSnapshot) Generated clients are not published. The OpenAPI document is the contract they will follow. Ignore unknown JSON fields, and branch on `error`. # FAQ (/docs/faq) ## Does the tracker set a cookie? [#does-the-tracker-set-a-cookie] No. Essential analytics is cookieless. The consent choice, once a visitor makes one, is `localStorage` on their site under `databob.consent.`. ## Why is the dashboard not showing my pageview? [#why-is-the-dashboard-not-showing-my-pageview] Realtime, Pages, and Sources are not connected. The collect response `202` with `{ "stored": true }` is the first pageview. Counts are on the data API after the daily snapshot rebuild at 04:00 UTC. Until then the API returns zeros and `enough_data: false`. ## Which key goes in the script tag? [#which-key-goes-in-the-script-tag] The write key, prefix `dbw_`. It is shown once on Overview. It is not accepted on the data API. ## Which key goes on the data API? [#which-key-goes-on-the-data-api] `Authorization: Bearer` with `dbk_live_` or `dbk_test_`. Create it under API keys. The prefix is a label. A missing, unknown, or revoked key is `401`. ## Can I query a content id the script never sent? [#can-i-query-a-content-id-the-script-never-sent] The script does not send `content_id`, so the stored id is the pathname, such as `/pricing`. Pass that as `content_id`. A direct collect body can send a different `content_id`. The OpenAPI samples use `post_123` as that kind of id. ## What does Global Privacy Control do? [#what-does-global-privacy-control-do] The banner stays hidden and enhanced analytics stays off, including when the region is Everywhere. The Worker does the same when it sees `Sec-GPC: 1` or `DNT: 1`. ## Are California visitors prompted? [#are-california-visitors-prompted] No. They stay on cookieless analytics. They can still open Privacy choices. Global Privacy Control is honored. ## How many API calls can I make? [#how-many-api-calls-can-i-make] 120 requests per key per 60 seconds, and 600 per org in that same window. Over the limit is `429` with `Retry-After`. An org can have 25 active keys. ## Is there an SDK? [#is-there-an-sdk] Not yet. Use the HTTP API. The contract is `docs/data-api.openapi.yaml`. ## Is there an EU ingest endpoint? [#is-there-an-eu-ingest-endpoint] Not yet. Collect is `https://us-ingest.databob.dev/v1/collect`. ## How do I pay? [#how-do-i-pay] You don't, in this release. The dashboard plan is Free. Billing is not turned on. Pricing on the marketing site is a placeholder. # Introduction (/docs) Databob records pageviews without a cookie. Enhanced analytics, the campaign, the referring site, and a goal event, stays off until a visitor accepts it. One script tag loads the tracker. Convex holds the control plane and the content snapshots. A page read returns a stored snapshot. It does not query Cloudflare Workers Analytics Engine on the request. Sign up, add a site, install the snippet, and confirm the first pageview. Script attributes, the collect endpoint, and what a pageview stores. Categories, regions, Global Privacy Control, and the hosted privacy choices page. Read a content snapshot with a dbk\_live\_ or dbk\_test\_ key. ## What is live [#what-is-live] | Piece | Where it lives | | ---------------------- | --------------------------------------------------------- | | Tracker | `https://databob.dev/databob.js`, about 12 KB minified | | Collect | `POST https://us-ingest.databob.dev/v1/collect` | | Dashboard | `https://databob.dev/dashboard` | | Data API | `https://api.databob.dev`, version `1`, paths under `/v1` | | Hosted privacy choices | `https://databob.dev/c/` | The only public report is the content snapshot. Realtime, Pages, and Sources in the dashboard are not connected yet. Official SDKs are not published. EU ingest is not published. Billing is not turned on, and the plan shown in the dashboard is Free. Pricing on the marketing site is still a placeholder. ## For coding agents [#for-coding-agents] [Install databob with an AI agent](/docs/agents) points at [`/llms.txt`](/llms.txt), [`/llms-full.txt`](/llms-full.txt), and a Markdown copy of every page. # Privacy and compliance (/docs/privacy) This page describes what Databob stores. It is not legal advice. Your privacy policy, your lawful basis, and your notices are yours to write. The banner can link to an `https` privacy policy when you set one. ## Cookieless by default [#cookieless-by-default] The tracker does not set a cookie. The essential choice is not a cookie either. It is `localStorage` on the customer site, and only after a banner choice or a Global Privacy Control opt-out. A stored point does not include: * IP address * The full user agent * Email * A visitor id Country comes from the edge country code. Device class is `mobile`, `tablet`, `desktop`, or `other`, from `Sec-CH-UA-Mobile` and a short check of the user agent. The full user agent string is not written to the point. ## What is collected [#what-is-collected] **Anonymous pageview.** This is the default, and it is what you get when enhanced analytics is off, when the visitor has not accepted, or when Global Privacy Control or Do Not Track is on. | Field | Example | | ------------ | -------------------------------------------------------- | | Path | `/pricing`, with the query string and fragment removed | | Content id | The path, unless a direct collect body sent `content_id` | | Country | `US`, `DE`, or empty when the country is unknown | | Device class | `desktop` | **Enhanced pageview.** Stored only when enhanced analytics is on for the project, `consent.analytics` is `granted`, `consent.version` matches the version returned with the write key, and the request is not opted out by Global Privacy Control or Do Not Track. The extra fields are the referrer host (not the full referrer URL) and UTM source, medium, and campaign. A goal event can be stored in that same tier. The goal name has to match the name configured on the project. **Consent event.** Action `granted`, `denied`, or `changed`, category `enhanced`, the version, and the source. No path, country, address, or visitor id. A direct `POST` that only says analytics is granted stays anonymous. The Worker still requires the matching consent version from a real choice. `consent.source` does not raise the tier. ## GDPR [#gdpr] Visitors in the EU, the EEA, the UK, Switzerland, and Canada are asked before enhanced analytics. Essential cookieless measurement stays on and does not use a cookie. Accept, Reject, and Customize are equal buttons. Enhanced starts unchecked. Reject, or closing the choice without ticking enhanced, keeps the anonymous tier. Changing the banner text, the policy URL, the enhanced label, the region, or the enhanced toggle asks again. Global Privacy Control and Do Not Track opt out of the enhanced tier everywhere, including inside the EU list. ## CCPA [#ccpa] California visitors are not prompted and stay on cookieless analytics. Global Privacy Control is honored for them, the same as everywhere else: the banner stays hidden and enhanced analytics stays off. The hosted privacy choices page at `/c/` is where a visitor can still opt in or out. Databob does not sell personal information in the product, and it does not store a visitor id that could be sold. There is no separate "Do Not Sell" endpoint beyond that choices page and Global Privacy Control. ## Retention in the product [#retention-in-the-product] Ingest writes to Workers Analytics Engine. The dashboard and the data API read Convex snapshots, not the raw points, on a page request. Content snapshots are rebuilt daily at 04:00 UTC for the `7d` and `28d` windows. `enough_data` is false when the current window was extrapolated from fewer than three unweighted rows. That row count is not part of the snapshot. There is no data processing addendum, no EU ingest region, and no billing plan beyond Free in this release. # Quickstart (/docs/quickstart) The dashboard copies a single script tag. The framework examples below set the same attributes. Replace `YOUR_SITE_ID` with the project id and `YOUR_WRITE_KEY` with the `dbw_` secret shown once when you create the site. ### Sign up [#sign-up] Create an account at [databob.dev/sign-up](https://databob.dev/sign-up). Sign-in is Clerk. Organizations and billing are off. The first sign-in creates a free org. If the Clerk webhook is late, the dashboard creates that same org once. A deleted account is not created again. ### Add a site [#add-a-site] Open [Overview](https://databob.dev/dashboard). Create a project with a name, an `https` site URL, and an optional goal event name. The site URL allows that host and its `www` counterpart. `https://example.com` also allows `https://www.example.com`, and the other way around. The write key is shown once. Rotating it makes the old key stop working immediately. The key starts with `dbw_`. It is not a data API key. ### Install the snippet [#install-the-snippet] Paste the tag on the site whose origin you just allowed. The script will not send a pageview from a different origin. The dashboard copies this exact tag. `YOUR_SITE_ID` and `YOUR_WRITE_KEY` are placeholders until the secret is on screen. ```html title="index.html" ``` ```tsx title="app/databob.tsx" {9} import Script from "next/script"; export function Databob() { return ( ``` Collect is `us-ingest.databob.dev` only. There is no EU ingest hostname in this release. ## What the browser sends [#what-the-browser-sends] A pageview is `POST /v1/collect` with the write key in the JSON body. The body is sent with `navigator.sendBeacon` when that is available, otherwise `fetch` with `keepalive`. The tracker sends: ```json title="pageview.json" { "write_key": "dbw_…", "type": "pageview", "path": "/pricing", "consent": { "analytics": "denied", "source": "databob" } } ``` `path` is the pathname. The query string and fragment are not part of the stored path. `consent.analytics` is `granted` only when enhanced analytics is on, the visitor accepted the current consent version, and the browser is not opted out. When it is granted, the body also includes `consent.version`, the document referrer, and `utm_source`, `utm_medium`, and `utm_campaign` when those query parameters are present. The published script does not set `content_id`. The Worker then stores the pathname as the content id. A direct `POST` may include `content_id`. The query string and fragment are removed from that value. An empty value falls back to the pathname. ## Collect responses [#collect-responses] The request origin has to be one of the project's allowed origins. A missing `Origin` header is refused. | Result | Status | Body | | -------------------------------------------- | ------ | ---------------------------------------------------- | | Anonymous pageview stored | 202 | `{ "stored": true }` | | Pageview stored with the richer consent tier | 202 | `{ "stored": true }` | | Consent choice stored | 202 | `{ "stored": true }` | | Goal event without the richer consent tier | 200 | `{ "stored": false, "reason": "consent" }` | | Goal name is not the project's goal | 200 | `{ "stored": false, "reason": "event" }` | | Write key missing | 400 | `{ "stored": false, "reason": "missing_write_key" }` | | Write key unknown | 401 | `{ "stored": false, "reason": "unknown_write_key" }` | | Origin not allowed | 403 | `{ "stored": false, "reason": "origin" }` | `Sec-GPC: 1` and `DNT: 1` force the anonymous tier even when the visitor granted analytics and the version matches. `consent.source` is accepted and ignored for that decision. ## Goals [#goals] `databob.track(name)` sends a goal event. The optional second argument is a finite number. It defaults to `1`. ```js title="goal.js" {1} databob.track("signup"); databob.track("signup", 1); ``` The event is stored only when all of these are true: * Enhanced analytics is on for the project. * The visitor granted the current consent version, and the browser is not sending Global Privacy Control or Do Not Track. * `name` matches the goal event name saved on the project. Any other name returns `200` with `reason: "event"` and stores nothing. The call does nothing if the tracker has not finished loading config, or if the richer tier is not active. It does not throw. ## Region lookup [#region-lookup] When the banner is limited to the EU, the EEA, the UK, Switzerland, and Canada, the script calls `GET /v1/region` on the collect host. That route returns `{ "country": "DE" }` and writes nothing. An unknown country is asked. Visitors outside that list are not asked. ## Config cache [#config-cache] The public consent document and the write-key lookup are cached for 60 seconds. A consent edit can take about a minute to apply on new pageviews. # GET /v1/reports/content (/docs/api/getContentReport) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} ## GET /v1/reports/content [#get-v1reportscontent] ## Authentication [#authentication] Send `Authorization: Bearer` with the full `dbk_live_` or `dbk_test_` secret. The prefix is a label. Authorization is the HMAC of the secret. ## Parameters and response [#parameters-and-response] Playground, code samples, and the response schema below are generated from `docs/data-api.openapi.yaml`. # GET /v1/snapshots/content (/docs/api/getContentSnapshot) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} ## GET /v1/snapshots/content [#get-v1snapshotscontent] ## Authentication [#authentication] Send `Authorization: Bearer` with the full `dbk_live_` or `dbk_test_` secret. The prefix is a label. Authorization is the HMAC of the secret. ## Parameters and response [#parameters-and-response] Playground, code samples, and the response schema below are generated from `docs/data-api.openapi.yaml`. # API reference (/docs/api) These pages are generated from `docs/data-api.openapi.yaml` in the databob repo. The server URL in the document is `https://api.databob.dev`. The playground on each operation sends the request through this site's proxy so the browser can call that API. Send `Authorization: Bearer` with a `dbk_live_` or `dbk_test_` key. Code samples are curl, JavaScript, and Python. Response examples and the error codes `400`, `401`, `403`, `404`, and `429` come from the document. `500` with `error: unavailable` is included when the pepper is missing. Read the snapshot and record the content ids for the next daily rebuild. Read the same snapshot without recording a rebuild request. Guides for query parameters and limits are [Data API](/docs/data-api) and [Rate limits and errors](/docs/rate-limits).