{"openapi":"3.1.0","info":{"title":"SEED analytics API","version":"v1","description":"Read access to SEED Global Education’s first-party website analytics, for the company’s own systems: headline figures, pages and sections, traffic sources, campaigns, forms, every recorded event, visitors and their journeys, and — for server keys granted it — the personal details people gave us. Every request needs an API key from the dashboard’s \"API access\" section. Answers are JSON in one envelope, `{ data, meta }`, and fields are stable within v1: they are never renamed, removed or given a new meaning. The guide at /api-docs.html explains keys, permissions, pagination, dates and limits."},"servers":[{"url":"https://analytics.seedglobaleducation.com","description":"Production"}],"externalDocs":{"description":"Guide and reference","url":"https://analytics.seedglobaleducation.com/api-docs.html"},"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"tags":[{"name":"Account","description":"Who the key belongs to, what it may read and which endpoints it can call."},{"name":"Stats","description":"Aggregated numbers for a range of days: visitors, pages, sections, sources, campaigns, devices, countries, forms and automated traffic. Needs the \"stats\" permission."},{"name":"Catalogue","description":"The sections each page carries (its data-sa-section markers) and their names, as the pages look now. Needs the \"catalogue\" permission."},{"name":"Events","description":"Every recorded event, row by row, newest first. Needs the \"events\" permission."},{"name":"Visitors","description":"Visitors under their anonymous visitor ids, with their sessions and journeys. Needs the \"visitors\" permission."},{"name":"Sessions","description":"Single visits: when they started and ended, where they came in and what they did."},{"name":"People","description":"Personal details: names, emails and phone numbers. Only for a server key holding the \"people\" permission; a key used from web pages never reads these."}],"x-scopes":[{"scope":"stats","description":"Aggregated numbers: visitors, pages, sections, sources, campaigns, devices, countries, forms, bots."},{"scope":"events","description":"Every recorded event, row by row."},{"scope":"visitors","description":"Visitors, their sessions and their journeys, under anonymous visitor ids."},{"scope":"people","description":"Personal details wherever they exist: names, emails, phone numbers, IP addresses, user agents."},{"scope":"catalogue","description":"The sections each page carries (data-sa-section) and their names."}],"x-limits":{"default_days":30,"max_days":400},"paths":{"/v1":{"get":{"operationId":"getAccount","summary":"Who am I, and what can I call","description":"The first request any integration should make. Answers with the key it was made with — its name, the permissions it holds, whether it is a browser key, which sites it may read, its rate limit and whether it can see personal data — and the endpoints this key may call. Needs no permission: any active key may ask about itself.","tags":["Account"],"x-scope":null,"parameters":[],"responses":{"200":{"description":"The key and the endpoints it may call.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","required":["api","version","docs","openapi","key","endpoints"],"properties":{"api":{"type":"string","description":"Always \"SEED analytics\"."},"version":{"type":"string","description":"Always \"v1\" on this version of the API."},"docs":{"type":"string","description":"Where the human-readable reference lives."},"openapi":{"type":"string","description":"Where this OpenAPI document lives."},"key":{"type":"object","description":"The key this request was made with.","required":["key_id","name","scopes","browser_origins","sites","rate_limit_per_min","personal_data"],"properties":{"key_id":{"type":"string","description":"The key’s public id: `key_` and the 10 characters after `sak_` in the key itself. Not a secret."},"name":{"type":"string","description":"The name it was given in the dashboard."},"scopes":{"type":"array","description":"The permissions the key holds.","items":{"type":"object","required":["scope","description"],"properties":{"scope":{"type":"string","enum":["stats","events","visitors","people","catalogue"],"description":"The permission."},"description":{"type":"string","description":"What it lets the key read."}}}},"browser_origins":{"type":"array","items":{"type":"string"},"description":"Web addresses allowed to use this key from a browser. Empty for a server key."},"sites":{"description":"The sites the key may read: a list of hostnames, or \"all\".","oneOf":[{"type":"array","items":{"type":"string"}},{"type":"string","enum":["all"]}]},"rate_limit_per_min":{"type":"integer","description":"Requests the key may make per clock minute."},"personal_data":{"type":"boolean","description":"True when this key sees personal details: it holds \"people\" and is a server key."}}},"endpoints":{"type":"array","description":"The endpoints this key may call: the ones needing no permission, and every one whose permission it holds.","items":{"type":"object","required":["method","path","summary","scope"],"properties":{"method":{"type":"string","description":"HTTP method, e.g. GET."},"path":{"type":"string","description":"The path, with {placeholders} for ids."},"summary":{"type":"string","description":"What it answers, in a few words."},"scope":{"type":["string","null"],"enum":["stats","events","visitors","people","catalogue",null],"description":"The permission it needs, or null for none."}}}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":{"api":"SEED analytics","version":"v1","docs":"/api-docs.html","openapi":"/v1/openapi.json","key":{"key_id":"key_k7m2q9x4Ab","name":"CRM nightly sync","scopes":[{"scope":"stats","description":"Aggregated numbers: visitors, pages, sections, sources, campaigns, devices, countries, forms, bots."},{"scope":"events","description":"Every recorded event, row by row."}],"browser_origins":[],"sites":"all","rate_limit_per_min":120,"personal_data":false},"endpoints":[{"method":"GET","path":"/v1","summary":"Who am I, and what can I call","scope":null},{"method":"GET","path":"/v1/stats/overview","summary":"Headline figures for a range","scope":"stats"}]},"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/sites":{"get":{"operationId":"listSites","summary":"The sites with data","description":"Every website that has sent data, as the hostname to pass as `?site=` elsewhere. Not tied to a date range: a site is listed if it has sent anything in the data held. A leading `www.` is removed, so www.seedglobaleducation.com and seedglobaleducation.com are one site. A key limited to certain sites sees only those. Needs no permission: any active key may ask which sites it can read. `limit`: 100 rows by default, at most 1000.","tags":["Account"],"x-scope":null,"parameters":[{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"The sites.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"One entry per website, most visitors first.","items":{"type":"object","description":"One website.","required":["site","site_id","recognised","visitors","pageviews","last_seen_day"],"properties":{"site":{"type":"string","description":"The hostname with any leading `www.` removed. Pass it as `?site=` to any other endpoint."},"site_id":{"type":["string","null"],"description":"Our internal id for the site (`b2c`, `finder`, `finder_legacy` or `unknown`), for context only. It is the id the collector stamped on this host’s events, which older events lack, so filter by `site`."},"recognised":{"type":"boolean","description":"True for one of SEED’s known sites. False for anything else that sent data, such as a staging deploy."},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors. A visitor is one browser: the same person on a phone and a laptop counts twice. Counted over all the data held, not a date range."},"pageviews":{"type":"integer","minimum":0,"description":"Pages opened, over all the data held."},"last_seen_day":{"type":["string","null"],"format":"date","description":"The last UTC day this site sent anything, YYYY-MM-DD."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"site":"seedglobaleducation.com","site_id":"b2c","recognised":true,"visitors":21480,"pageviews":61230,"last_seen_day":"2026-09-21"},{"site":"finder.seedglobaleducation.com","site_id":"finder_legacy","recognised":true,"visitors":6120,"pageviews":7410,"last_seen_day":"2026-09-21"}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"bots":"human","limit":100}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/overview":{"get":{"operationId":"getStatsOverview","summary":"Headline figures for a range","description":"The numbers at the top of the dashboard for a range of days: visitors, sessions, page views, people who sent a form or clicked out to contact us, identified visitors, average visit length and bounce rate. Add `compare=true` for the same figures over the period just before, with the change in each. `utm_campaign` and `utm_source` narrow it to one campaign or one source code, counting the events that carried the tag. `meta.query` repeats what was applied. Under a campaign filter `identified_visitors` is null: that one count cannot be narrowed to a campaign, and a whole-site number beside narrowed ones would be read as a narrowed one.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/UtmCampaign"},{"$ref":"#/components/parameters/UtmSource"},{"name":"compare","in":"query","required":false,"description":"true to add `comparison`: the same figures for the period of equal length just before `from`, with the relative change of each. Default false, which leaves `comparison` null and costs half the work.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"The headline figures.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","description":"The headline figures for the range.","required":["visitors","sessions","pageviews","events","form_submitters","form_submissions","form_submitter_pct","outbound_clickers","outbound_clicks","identified_visitors","avg_session_seconds","avg_events_per_session","bounce_rate_pct","comparison"],"properties":{"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors. A visitor is one browser: the same person on a phone and a laptop counts twice."},"sessions":{"type":"integer","minimum":0,"description":"Distinct sessions (visits). A session ends after 30 minutes without activity."},"pageviews":{"type":"integer","minimum":0,"description":"Pages opened. The same person opening the same page twice counts twice."},"events":{"type":"integer","minimum":0,"description":"Every recorded event of any kind: page views, section views, clicks, form events."},"form_submitters":{"type":"integer","minimum":0,"description":"Visitors who sent at least one form (a `form_submit` event). This is the dashboard’s \"Enquiries\" figure. It counts every form a page reports, including sign-in and newsletter boxes. For registrations page by page, see GET /v1/stats/forms."},"form_submissions":{"type":"integer","minimum":0,"description":"`form_submit` events. Above `form_submitters` when people send more than one form."},"form_submitter_pct":{"type":["number","null"],"description":"`form_submitters` as a percentage of `visitors`, 0–100, one decimal. The dashboard’s \"Out of every 100 visitors\". null when there were no visitors."},"outbound_clickers":{"type":"integer","minimum":0,"description":"Visitors who clicked a link off the site: WhatsApp, phone, email, a university site, the course finder. The dashboard’s \"Got in touch another way\"."},"outbound_clicks":{"type":"integer","minimum":0,"description":"Clicks on links off the site."},"identified_visitors":{"type":["integer","null"],"minimum":0,"description":"Visitors with at least one event recorded after the site identified them: they signed in or gave us their details. A count only; no personal data. null when `utm_campaign` or `utm_source` was given: this is the one figure here that cannot be narrowed to a campaign, and it is left out rather than answered for the whole site beside figures that were narrowed."},"avg_session_seconds":{"type":["number","null"],"description":"Average session length in seconds, one decimal: from the first to the last event of each session, so a one-page visit counts as 0. Most visits are one page, which pulls this down. null when there were no sessions."},"avg_events_per_session":{"type":["number","null"],"description":"Average events per session, two decimals. null when there were no sessions."},"bounce_rate_pct":{"type":["number","null"],"description":"Sessions with at most one page view, as a percentage, 0–100, one decimal. Mostly a measure of how many people accept cookies: we can follow someone between pages only once they have. null when there were no sessions."},"comparison":{"type":["object","null"],"description":"Only with `compare=true`, otherwise null. The same figures for the period of equal length that ends the day before `from`. If `to` is today, the current period includes a day still being written to, and a drop is to be expected. End `to` yesterday for a like-for-like comparison.","required":["from","to","visitors","sessions","pageviews","events","form_submitters","form_submissions","form_submitter_pct","outbound_clickers","outbound_clicks","identified_visitors","avg_session_seconds","avg_events_per_session","bounce_rate_pct","change_pct"],"properties":{"from":{"type":"string","format":"date","description":"First day of the previous period, YYYY-MM-DD."},"to":{"type":"string","format":"date","description":"Last day of the previous period, YYYY-MM-DD: the day before `from`."},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors. A visitor is one browser: the same person on a phone and a laptop counts twice."},"sessions":{"type":"integer","minimum":0,"description":"Distinct sessions (visits). A session ends after 30 minutes without activity."},"pageviews":{"type":"integer","minimum":0,"description":"Pages opened. The same person opening the same page twice counts twice."},"events":{"type":"integer","minimum":0,"description":"Every recorded event of any kind: page views, section views, clicks, form events."},"form_submitters":{"type":"integer","minimum":0,"description":"Visitors who sent at least one form (a `form_submit` event). This is the dashboard’s \"Enquiries\" figure. It counts every form a page reports, including sign-in and newsletter boxes. For registrations page by page, see GET /v1/stats/forms."},"form_submissions":{"type":"integer","minimum":0,"description":"`form_submit` events. Above `form_submitters` when people send more than one form."},"form_submitter_pct":{"type":["number","null"],"description":"`form_submitters` as a percentage of `visitors`, 0–100, one decimal. The dashboard’s \"Out of every 100 visitors\". null when there were no visitors."},"outbound_clickers":{"type":"integer","minimum":0,"description":"Visitors who clicked a link off the site: WhatsApp, phone, email, a university site, the course finder. The dashboard’s \"Got in touch another way\"."},"outbound_clicks":{"type":"integer","minimum":0,"description":"Clicks on links off the site."},"identified_visitors":{"type":["integer","null"],"minimum":0,"description":"Visitors with at least one event recorded after the site identified them: they signed in or gave us their details. A count only; no personal data. null when `utm_campaign` or `utm_source` was given: this is the one figure here that cannot be narrowed to a campaign, and it is left out rather than answered for the whole site beside figures that were narrowed."},"avg_session_seconds":{"type":["number","null"],"description":"Average session length in seconds, one decimal: from the first to the last event of each session, so a one-page visit counts as 0. Most visits are one page, which pulls this down. null when there were no sessions."},"avg_events_per_session":{"type":["number","null"],"description":"Average events per session, two decimals. null when there were no sessions."},"bounce_rate_pct":{"type":["number","null"],"description":"Sessions with at most one page view, as a percentage, 0–100, one decimal. Mostly a measure of how many people accept cookies: we can follow someone between pages only once they have. null when there were no sessions."},"change_pct":{"type":"object","description":"Relative change of each figure: (current − previous) ÷ previous × 100.","required":["visitors","sessions","pageviews","events","form_submitters","form_submissions","form_submitter_pct","outbound_clickers","outbound_clicks","identified_visitors","avg_session_seconds","avg_events_per_session","bounce_rate_pct"],"properties":{"visitors":{"type":["number","null"],"description":"Relative change in `visitors` from the previous period, in percent, one decimal. null when the previous value is 0 or null."},"sessions":{"type":["number","null"],"description":"Relative change in `sessions` from the previous period, in percent, one decimal. null when the previous value is 0 or null."},"pageviews":{"type":["number","null"],"description":"Relative change in `pageviews` from the previous period, in percent, one decimal. null when the previous value is 0 or null."},"events":{"type":["number","null"],"description":"Relative change in `events` from the previous period, in percent, one decimal. null when the previous value is 0 or null."},"form_submitters":{"type":["number","null"],"description":"Relative change in `form_submitters` from the previous period, in percent, one decimal. null when the previous value is 0 or null."},"form_submissions":{"type":["number","null"],"description":"Relative change in `form_submissions` from the previous period, in percent, one decimal. null when the previous value is 0 or null."},"form_submitter_pct":{"type":["number","null"],"description":"Relative change in `form_submitter_pct` from the previous period, in percent, one decimal. null when the previous value is 0 or null."},"outbound_clickers":{"type":["number","null"],"description":"Relative change in `outbound_clickers` from the previous period, in percent, one decimal. null when the previous value is 0 or null."},"outbound_clicks":{"type":["number","null"],"description":"Relative change in `outbound_clicks` from the previous period, in percent, one decimal. null when the previous value is 0 or null."},"identified_visitors":{"type":["number","null"],"description":"Relative change in `identified_visitors` from the previous period, in percent, one decimal. null when the previous value is 0 or null."},"avg_session_seconds":{"type":["number","null"],"description":"Relative change in `avg_session_seconds` from the previous period, in percent, one decimal. null when the previous value is 0 or null."},"avg_events_per_session":{"type":["number","null"],"description":"Relative change in `avg_events_per_session` from the previous period, in percent, one decimal. null when the previous value is 0 or null."},"bounce_rate_pct":{"type":["number","null"],"description":"Relative change in `bounce_rate_pct` from the previous period, in percent, one decimal. null when the previous value is 0 or null."}}}}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":{"visitors":9120,"sessions":12840,"pageviews":31260,"events":88410,"form_submitters":612,"form_submissions":701,"form_submitter_pct":6.7,"outbound_clickers":1480,"outbound_clicks":2215,"identified_visitors":388,"avg_session_seconds":74.2,"avg_events_per_session":6.89,"bounce_rate_pct":71.4,"comparison":{"from":"2026-07-24","to":"2026-08-22","visitors":8440,"sessions":11900,"pageviews":29870,"events":80120,"form_submitters":540,"form_submissions":611,"form_submitter_pct":6.4,"outbound_clickers":1390,"outbound_clicks":2010,"identified_visitors":301,"avg_session_seconds":69.8,"avg_events_per_session":6.73,"bounce_rate_pct":72.9,"change_pct":{"visitors":8.1,"sessions":7.9,"pageviews":4.7,"events":10.3,"form_submitters":13.3,"form_submissions":14.7,"form_submitter_pct":4.7,"outbound_clickers":6.5,"outbound_clicks":10.2,"identified_visitors":28.9,"avg_session_seconds":6.3,"avg_events_per_session":2.4,"bounce_rate_pct":-2.1}}},"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","utm_campaign":null,"utm_source":null,"compare":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/timeseries":{"get":{"operationId":"getStatsTimeseries","summary":"Figures day by day","description":"Events, visitors and sessions for each UTC day of the range, oldest first, with quiet days as zeros. Pass `event` to count one kind of event, e.g. `event=form_submit` for form submissions a day (`visitors` is then the people who sent one). `utm_campaign` and `utm_source` narrow it to one campaign or one source code, counting the events that carried the tag. `meta.query` repeats what was applied.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/UtmCampaign"},{"$ref":"#/components/parameters/UtmSource"},{"name":"event","in":"query","required":false,"description":"Count only this event, e.g. `pageview` or `form_submit`. GET /v1/stats/events lists the names. Default: every event.","schema":{"type":"string","maxLength":200,"example":"form_submit"}},{"name":"interval","in":"query","required":false,"description":"The width of each point. Only `day` (UTC days) exists today; other widths may be added.","schema":{"type":"string","enum":["day"],"default":"day"}}],"responses":{"200":{"description":"One entry per day.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"One entry per UTC day from `from` to `to`, oldest first. Days with nothing recorded are present as zeros.","items":{"type":"object","description":"One day.","required":["day","events","visitors","sessions"],"properties":{"day":{"type":"string","format":"date","description":"The UTC day, YYYY-MM-DD."},"events":{"type":"integer","minimum":0,"description":"Events on this day (only `event`, when given). With `event=pageview` this is page views."},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors. A visitor is one browser: the same person on a phone and a laptop counts twice. Distinct within the day."},"sessions":{"type":"integer","minimum":0,"description":"Distinct sessions with an event on this day."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"day":"2026-09-19","events":41,"visitors":38,"sessions":39},{"day":"2026-09-20","events":0,"visitors":0,"sessions":0},{"day":"2026-09-21","events":27,"visitors":25,"sessions":25}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-09-19","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","utm_campaign":null,"utm_source":null,"event":"form_submit","interval":"day"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/pages":{"get":{"operationId":"listStatsPages","summary":"Most-opened pages","description":"The pages people opened most in the range, with how many people opened each. `limit`: 100 rows by default, at most 1000. `utm_campaign` and `utm_source` narrow it to one campaign or one source code, counting the events that carried the tag. `meta.query` repeats what was applied.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/UtmCampaign"},{"$ref":"#/components/parameters/UtmSource"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"The pages.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"The most-opened pages, most page views first.","items":{"type":"object","description":"One page.","required":["path","pageviews","visitors"],"properties":{"path":{"type":"string","description":"The page’s path, e.g. `/study-abroad/usa`. Without `site`, the same path on two sites (both have `/`) is one entry; pass `site` to keep them apart. Any email address in it is shown as `redacted`."},"pageviews":{"type":"integer","minimum":0,"description":"Times the page was opened."},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors. A visitor is one browser: the same person on a phone and a laptop counts twice. Visitors who opened this page."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"path":"/","pageviews":5310,"visitors":4120},{"path":"/study-abroad/events/in-person","pageviews":1880,"visitors":1402}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","utm_campaign":null,"utm_source":null,"limit":100}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/section-pages":{"get":{"operationId":"listStatsSectionPages","summary":"Pages with time-on-section data","description":"The pages for which we measured how long people spent on each part, most visitors first. It is step one of two: take a `path` from here to GET /v1/stats/sections. `limit`: 100 rows by default, at most 1000. `utm_campaign` and `utm_source` narrow it to one campaign or one source code, counting the events that carried the tag. `meta.query` repeats what was applied. GET /v1/stats/sections itself does not take them: it reads the section rollup, which has no campaign columns, so the second step is always every campaign together.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/UtmCampaign"},{"$ref":"#/components/parameters/UtmSource"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"The pages.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"Pages with time-on-section data, most visitors first. Pick a `path` here for GET /v1/stats/sections.","items":{"type":"object","description":"One page on one site.","required":["path","site_id","page_type","visitors","section_views"],"properties":{"path":{"type":"string","description":"The page’s path, exactly as GET /v1/stats/sections takes it. Any email address in it is shown as `redacted`."},"site_id":{"type":["string","null"],"description":"Our internal site id (`b2c`, `finder`, …). null on data recorded before 25 Aug 2026."},"page_type":{"type":["string","null"],"description":"What kind of page it is, e.g. `home`, `event_detail`, `scholarship_list`. null on older data."},"visitors":{"type":"integer","minimum":0,"description":"Visitors who looked at one or more sections of the page long enough to be measured. Lower than the page’s own visitor count: someone who left at once never registers a section."},"section_views":{"type":"integer","minimum":0,"description":"Section measurements recorded. One visitor usually produces several: one per section, and another each time they come back to the tab."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"path":"/","site_id":"b2c","page_type":"home","visitors":3210,"section_views":28740},{"path":"/study-abroad/scholarships","site_id":"b2c","page_type":"scholarship_list","visitors":940,"section_views":6120}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","utm_campaign":null,"utm_source":null,"limit":100}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/sections":{"get":{"operationId":"listStatsSections","summary":"Time spent on each part of a page","description":"One page, section by section from the top: how many people looked at each part and for how long. The numbers and names are the dashboard’s: repeat ids are merged, renamed sections appear under their current name, and junk ids (countdown timers, positional names) are left out. With `site`, only that site’s data counts. A site that is not one of SEED’s known sites has no section data and answers with an empty list. `limit`: 100 rows by default, at most 1000.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/Limit"},{"name":"path","in":"query","required":true,"description":"The page, exactly as GET /v1/stats/section-pages lists it, e.g. `/study-abroad/usa`. Must start with `/`. Matched exactly as stored, so use the listed spelling.","schema":{"type":"string","maxLength":2048,"example":"/study-abroad/usa"}}],"responses":{"200":{"description":"The sections, top to bottom.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"The parts of one page, top to bottom, as the dashboard shows them.","items":{"type":"object","description":"One section of the page.","required":["section_id","label","position","section_views","visitors","avg_active_seconds","avg_visible_seconds","avg_max_visible_pct","first_day","last_day"],"properties":{"section_id":{"type":"string","description":"The section’s name after our naming rules: repeat suffixes removed (`awards-1` is `awards`), renamed sections under their current name, and an opening band named after its heading reported as `hero`."},"label":{"type":["string","null"],"description":"The heading most viewers saw on this section. null when it has none. Any email address in it is shown as `redacted`."},"position":{"type":"integer","minimum":0,"description":"Where it sits on the page, 0 for the first section."},"section_views":{"type":"integer","minimum":0,"description":"Measurements recorded for this section. One visitor can produce several."},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors. A visitor is one browser: the same person on a phone and a laptop counts twice. Visitors who looked at this section."},"avg_active_seconds":{"type":"number","description":"Seconds on screen with the tab in front and the visitor active, averaged per visitor, one decimal. Typing counts as active, so on a form section this is time spent filling it in."},"avg_visible_seconds":{"type":"number","description":"Seconds on screen, active or not, averaged per visitor, one decimal. Always at least `avg_active_seconds`."},"avg_max_visible_pct":{"type":"number","description":"How much of the section was on screen at its most, averaged, 0–100, one decimal. Approximate: it can read slightly low for visitors who switched tabs."},"first_day":{"type":["string","null"],"format":"date","description":"The first UTC day this section was recorded on this page in the range. Sections renamed or added part-way through a range have fewer days, so compare them with care."},"last_day":{"type":["string","null"],"format":"date","description":"The last UTC day this section was recorded on this page in the range."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"section_id":"hero","label":"Study in the USA","position":0,"section_views":1420,"visitors":1180,"avg_active_seconds":9.4,"avg_visible_seconds":14.1,"avg_max_visible_pct":96.2,"first_day":"2026-08-23","last_day":"2026-09-21"},{"section_id":"scholarships","label":"Available Scholarships","position":3,"section_views":610,"visitors":488,"avg_active_seconds":21.7,"avg_visible_seconds":30.2,"avg_max_visible_pct":81.5,"first_day":"2026-08-31","last_day":"2026-09-21"}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","path":"/study-abroad/usa","limit":100}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/section-dropoff":{"get":{"operationId":"listStatsSectionDropoff","summary":"Where people stop on each page","description":"Every page with time-on-section data, one row each, busiest first: how many people reached the part at the top of the page, how many reached the part at the bottom, and the share who reached the first and never the last — that share is `dropoff_pct`. First and last are by the order the parts appear down the page, the same order GET /v1/stats/sections lists them in, so the figures here and the parts of one page there are the same measurement for the same period. Reading down a page is not a funnel, though: `rose_anywhere` says when a lower part was reached by more people than a higher one, which makes `reached_end_pct` go above 100 and `dropoff_pct` below 0. Both are reported as measured, not clamped. THESE FIGURES ARE FOR THE WHOLE WEBSITE AND CANNOT BE NARROWED TO A CAMPAIGN: like GET /v1/stats/sections they read the stored per-part figures, which carry no campaign tags, so `utm_campaign` and `utm_source` are not accepted here rather than accepted and ignored. With `site`, only that site’s data counts; a site that is not one of SEED’s known sites has no section data and answers with an empty list. `limit`: 100 rows by default, at most 1000.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"The pages, busiest first.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"One page per entry, busiest first: how many people reached its first part and how many reached its last.","items":{"type":"object","description":"One page.","required":["path","site_id","page_type","parts","first_part_label","first_part_visitors","last_part_label","last_part_visitors","reached_end_pct","dropoff_pct","rose_anywhere"],"properties":{"path":{"type":"string","description":"The page’s path, exactly as GET /v1/stats/sections takes it. Any email address in it is shown as `redacted`."},"site_id":{"type":["string","null"],"description":"Our internal site id (`b2c`, `finder`, …). null when the page’s measurements do not all carry the same one — the same path served by two sites, or data recorded before 25 Aug 2026, which carries none."},"page_type":{"type":["string","null"],"description":"What kind of page it is, e.g. `home`, `event_detail`. null on older data, and when the page’s measurements do not all say the same kind."},"parts":{"type":"integer","minimum":0,"description":"How many parts of this page were measured in the range, after names are resolved. Parts added or renamed part-way through a range make this move, so a page can have more parts here than it has today."},"first_part_label":{"type":["string","null"],"description":"The heading of the part at the top of the page. null when that part has no heading. Any email address in it is shown as `redacted`."},"first_part_visitors":{"type":"integer","minimum":0,"description":"Distinct visitors. A visitor is one browser: the same person on a phone and a laptop counts twice. Visitors who reached the first part — the top of the page."},"last_part_label":{"type":["string","null"],"description":"The heading of the part at the bottom of the page. null when that part has no heading. Any email address in it is shown as `redacted`."},"last_part_visitors":{"type":"integer","minimum":0,"description":"Distinct visitors. A visitor is one browser: the same person on a phone and a laptop counts twice. Visitors who reached the last part — the bottom of the page."},"reached_end_pct":{"type":["number","null"],"description":"Of the people who reached the first part, the share who also reached the last, 0–100, one decimal. null when nobody reached the first part. Above 100 when more people reached the bottom than the top, which really happens — see `rose_anywhere`."},"dropoff_pct":{"type":["number","null"],"description":"The share who reached the first part and never reached the last: `100 - reached_end_pct`, one decimal. null when nobody reached the first part, and negative when more people reached the bottom than the top. Neither case is tidied up here."},"rose_anywhere":{"type":"boolean","description":"True when some part of the page was reached by more people than the part above it. Reading down a page is not a funnel: a band shared with another page, or a page re-marked part-way through the range, can leave a lower part with more people than a higher one. On such a page read the two counts as reach, not as loss, and treat the percentages as indicative only."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"path":"/study-abroad/scholarships","site_id":"b2c","page_type":"scholarship_list","parts":7,"first_part_label":"SEED Scholarships Fund","first_part_visitors":2872,"last_part_label":"Contact Us","last_part_visitors":177,"reached_end_pct":6.2,"dropoff_pct":93.8,"rose_anywhere":false},{"path":"/study-abroad/events/virtual","site_id":"b2c","page_type":"event_list","parts":5,"first_part_label":"Upcoming Virtual Masterclasses","first_part_visitors":410,"last_part_label":null,"last_part_visitors":437,"reached_end_pct":106.6,"dropoff_pct":-6.6,"rose_anywhere":true}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","limit":100}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/referrers":{"get":{"operationId":"listStatsReferrers","summary":"Websites that sent visitors","description":"Other websites people arrived from, most visitors first. Direct visits and most app traffic carry no referrer and are not listed. `limit`: 100 rows by default, at most 1000.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"The referring websites.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"Other websites that sent visitors, most visitors first. Visits with no referrer (typed in, bookmarks, most apps) are not listed.","items":{"type":"object","description":"One referring website.","required":["referrer_domain","visitors","sessions"],"properties":{"referrer_domain":{"type":"string","description":"The referring website’s hostname, e.g. `www.google.com`."},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors. A visitor is one browser: the same person on a phone and a laptop counts twice. Visitors with an event carrying this referrer."},"sessions":{"type":"integer","minimum":0,"description":"Sessions with an event carrying this referrer."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"referrer_domain":"www.google.com","visitors":2210,"sessions":2640},{"referrer_domain":"l.instagram.com","visitors":860,"sessions":910}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","limit":100}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/campaigns":{"get":{"operationId":"listStatsCampaigns","summary":"Tagged campaign links","description":"Visitors and sessions for each combination of UTM tags (source, medium, campaign), most visitors first. Untagged traffic is not listed. `limit`: 100 rows by default, at most 1000.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"The campaigns.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"Tagged campaign links, most visitors first. Each distinct combination of the three UTM tags is one entry.","items":{"type":"object","description":"One combination of UTM tags.","required":["utm_source","utm_medium","utm_campaign","visitors","sessions"],"properties":{"utm_source":{"type":["string","null"],"description":"The `utm_source` tag, e.g. an ambassador code like `SEED1864`. null when absent. Any email address in it is shown as `redacted`."},"utm_medium":{"type":["string","null"],"description":"The `utm_medium` tag, e.g. `email` or `influencer`. null when absent. Any email address in it is shown as `redacted`."},"utm_campaign":{"type":["string","null"],"description":"The `utm_campaign` tag. null when absent. Any email address in it is shown as `redacted`."},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors. A visitor is one browser: the same person on a phone and a laptop counts twice. Visitors with an event carrying these tags."},"sessions":{"type":"integer","minimum":0,"description":"Sessions with an event carrying these tags."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"utm_source":"SEED1864","utm_medium":"influencer","utm_campaign":"bsf-india-2026","visitors":412,"sessions":455},{"utm_source":"hs_email","utm_medium":"email","utm_campaign":null,"visitors":96,"sessions":101}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","limit":100}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/entry-pages":{"get":{"operationId":"listStatsEntryPages","summary":"Pages visits began on","description":"The pages sessions started on, most sessions first, with the share that left after one page. `limit`: 100 rows by default, at most 1000.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"The landing pages.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"The pages visits began on, most sessions first.","items":{"type":"object","description":"One landing page.","required":["path","sessions","bounce_rate_pct"],"properties":{"path":{"type":"string","description":"The page the session’s first event happened on. Any email address in it is shown as `redacted`."},"sessions":{"type":"integer","minimum":0,"description":"Sessions that began here."},"bounce_rate_pct":{"type":"number","description":"Of those, the sessions with at most one page view, 0–100, one decimal. Mostly a measure of cookie consent; see bounce_rate_pct on GET /v1/stats/overview."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"path":"/","sessions":3920,"bounce_rate_pct":68.2},{"path":"/study-abroad/events/virtual","sessions":1210,"bounce_rate_pct":74.9}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","limit":100}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/exit-links":{"get":{"operationId":"listStatsExitLinks","summary":"Links people clicked to leave","description":"Where people went when they clicked a link off the site, one entry per destination URL, most clicks first. Different placements of one link keep their own entries when their URLs differ (for example by UTM tags). Personal details in URLs are replaced with `redacted`. `limit`: 100 rows by default, at most 1000.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"The destinations.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"Links off the site that people clicked, most clicks first. One entry per destination URL.","items":{"type":"object","description":"One destination.","required":["url","domain","link_text","clicks","visitors"],"properties":{"url":{"type":"string","description":"Where the link went. Email addresses and the values of personal-looking query keys (email, phone, name…) are replaced with `redacted`, so two entries can show the same URL. The site’s own mailto: and tel: links are shown as they are."},"domain":{"type":["string","null"],"description":"The destination hostname, or the scheme (`tel`, `mailto`) for those links."},"link_text":{"type":["string","null"],"description":"The words on the link most clickers saw. When the link has no words (an icon, an image) this is the domain. Any email address in it is shown as `redacted`."},"clicks":{"type":"integer","minimum":0,"description":"Clicks on this link."},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors. A visitor is one browser: the same person on a phone and a laptop counts twice. Visitors who clicked it."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"url":"https://whatsapp.com/channel/0000ExampleChannel?utm_source=site&utm_medium=exit_intent","domain":"whatsapp.com","link_text":"Join WhatsApp Channel","clicks":1523,"visitors":1438},{"url":"tel:+10000000000","domain":"tel","link_text":"+10 00000 00000","clicks":25,"visitors":24}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","limit":100}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/devices":{"get":{"operationId":"listStatsDevices","summary":"Sessions by device","description":"Sessions on desktops, phones and tablets, with each one’s share. `limit`: 100 rows by default, at most 1000.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"The device kinds.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"Sessions by kind of device, most sessions first.","items":{"type":"object","description":"One kind of device.","required":["device_type","sessions","sessions_pct"],"properties":{"device_type":{"type":["string","null"],"description":"Usually `desktop`, `mobile` or `tablet`; the device detector can also report `smarttv`, `console`, `wearable` or `embedded`. null when it could not be told."},"sessions":{"type":"integer","minimum":0,"description":"Sessions on this kind of device. A session takes the device of its first event."},"sessions_pct":{"type":["number","null"],"description":"This kind’s share of all sessions, 0–100, one decimal."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"device_type":"mobile","sessions":8120,"sessions_pct":63.2},{"device_type":"desktop","sessions":4590,"sessions_pct":35.7},{"device_type":"tablet","sessions":130,"sessions_pct":1}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","limit":100}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/countries":{"get":{"operationId":"getStatsCountries","summary":"Visitors by country","description":"Where visitors were, one entry per country, counted per session: someone who visited from two countries counts in both. The location is taken from the network address when the visit happened, and the address itself is never returned. `unknown` is the share we could not place; `coverage` says how much of the range could be measured at all. `limit`: 100 rows by default, at most 1000. The limit applies to `countries`.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"Countries, the unplaced share and coverage.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","description":"Where visitors were, by country, with the share we could not place and how much of the range was measurable.","required":["countries","unknown","coverage"],"properties":{"countries":{"type":"array","description":"Located countries, most visitors first.","items":{"type":"object","description":"One country.","required":["country_code","country_name","visitors","sessions","pageviews","enquirers","phone_visitors"],"properties":{"country_code":{"type":"string","description":"ISO 3166-1 alpha-2 code, e.g. `IN`. Pass it as `country` to /regions and /cities."},"country_name":{"type":["string","null"],"description":"The country’s English name, e.g. `India`."},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors. A visitor is one browser: the same person on a phone and a laptop counts twice. Visitors with a session located in this country."},"sessions":{"type":"integer","minimum":0,"description":"Sessions located in this country."},"pageviews":{"type":"integer","minimum":0,"description":"Page views in those sessions."},"enquirers":{"type":"integer","minimum":0,"description":"Visitors who, in a session located in this country, sent a form or reached a thank-you (confirmation) page."},"phone_visitors":{"type":"integer","minimum":0,"description":"Visitors with a phone session located in this country."}}}},"unknown":{"type":"object","description":"Sessions we could not place. Countries plus this cover every session in the range.","required":["visitors","sessions","enquirers"],"properties":{"visitors":{"type":"integer","minimum":0,"description":"Visitors with a session we could not place."},"sessions":{"type":"integer","minimum":0,"description":"Sessions we could not place."},"enquirers":{"type":"integer","minimum":0,"description":"Visitors who sent a form or reached a confirmation page in such a session."}}},"coverage":{"type":"object","description":"How much of the range the location figures can see.","required":["visitors","located_visitors","located_pct","proxy_visitors","hosting_visitors","measuring_since","days"],"properties":{"visitors":{"type":"integer","minimum":0,"description":"Every visitor in the range, placed or not."},"located_visitors":{"type":"integer","minimum":0,"description":"Visitors with at least one located session."},"located_pct":{"type":["number","null"],"description":"`located_visitors` as a percentage of `visitors`, 0–100, one decimal."},"proxy_visitors":{"type":"integer","minimum":0,"description":"Located visitors whose location came through a proxy or VPN, so may be wrong."},"hosting_visitors":{"type":"integer","minimum":0,"description":"Located visitors whose address belongs to a hosting company, often software, not a person."},"measuring_since":{"type":["string","null"],"format":"date","description":"The first UTC day anyone was located, whatever the range. Days before it are unlocated for good, so a range reaching back past it shows a large unknown share that means \"not measured\", not \"nowhere\"."},"days":{"type":"array","description":"One entry per UTC day of the range, zeros included.","items":{"type":"object","description":"One day.","required":["day","visitors","located_visitors"],"properties":{"day":{"type":"string","format":"date","description":"The UTC day a session started on, YYYY-MM-DD."},"visitors":{"type":"integer","minimum":0,"description":"Visitors with a session starting that day."},"located_visitors":{"type":"integer","minimum":0,"description":"Of those, visitors with a located session starting that day."}}}}}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":{"countries":[{"country_code":"IN","country_name":"India","visitors":1820,"sessions":2610,"pageviews":9140,"enquirers":42,"phone_visitors":1500},{"country_code":"AE","country_name":"United Arab Emirates","visitors":410,"sessions":530,"pageviews":1720,"enquirers":12,"phone_visitors":300}],"unknown":{"visitors":2020,"sessions":2480,"enquirers":20},"coverage":{"visitors":4250,"located_visitors":2230,"located_pct":52.5,"proxy_visitors":90,"hosting_visitors":42,"measuring_since":"2026-09-15","days":[{"day":"2026-09-20","visitors":300,"located_visitors":158},{"day":"2026-09-21","visitors":281,"located_visitors":150}]}},"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","limit":100}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/regions":{"get":{"operationId":"getStatsRegions","summary":"Visitors by region of one country","description":"One country, region by region, counted the way GET /v1/stats/countries counts: per session, by where the session was. `limit`: 100 rows by default, at most 1000. The limit applies to `regions`.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/Limit"},{"name":"country","in":"query","required":true,"description":"The country, as an ISO 3166-1 alpha-2 code in capitals, e.g. `IN`. Lower case is refused rather than guessed.","schema":{"type":"string","pattern":"^[A-Z]{2}$","example":"IN"}}],"responses":{"200":{"description":"The country’s regions.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","description":"One country, by region.","required":["country_code","country_name","regions"],"properties":{"country_code":{"type":"string","description":"The country asked for."},"country_name":{"type":["string","null"],"description":"Its English name. null when nobody was located there in the range."},"regions":{"type":"array","description":"Regions (states, provinces, emirates), most visitors first. Sessions with no region are left out, so these need not add up to the country’s figures on /countries.","items":{"type":"object","description":"One region.","required":["region_code","region_name","visitors","sessions","pageviews","enquirers"],"properties":{"region_code":{"type":["string","null"],"description":"The region’s code from the location provider, e.g. `MH`."},"region_name":{"type":["string","null"],"description":"The region’s English name, e.g. `Maharashtra`."},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors. A visitor is one browser: the same person on a phone and a laptop counts twice. Visitors with a session located in this region."},"sessions":{"type":"integer","minimum":0,"description":"Sessions located in this region."},"pageviews":{"type":"integer","minimum":0,"description":"Page views in those sessions."},"enquirers":{"type":"integer","minimum":0,"description":"Visitors who, in a session located in this region, sent a form or reached a thank-you (confirmation) page."}}}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":{"country_code":"IN","country_name":"India","regions":[{"region_code":"DL","region_name":"Delhi","visitors":720,"sessions":980,"pageviews":3100,"enquirers":19},{"region_code":"MH","region_name":"Maharashtra","visitors":540,"sessions":700,"pageviews":2450,"enquirers":12}]},"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","country":"IN","limit":100}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/cities":{"get":{"operationId":"listStatsCities","summary":"Visitors by city","description":"The cities visitors were in, worldwide or in one `country`, counted per session. `limit`: 100 rows by default, at most 1000.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/Limit"},{"name":"country","in":"query","required":false,"description":"Limit to one country, as an ISO 3166-1 alpha-2 code in capitals, e.g. `IN`. Default: worldwide.","schema":{"type":"string","pattern":"^[A-Z]{2}$","example":"IN"}}],"responses":{"200":{"description":"The cities.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"Cities, most visitors first. A city is a city in a region in a country, so two cities with one name stay apart. Sessions with no city are left out.","items":{"type":"object","description":"One city.","required":["city","region_name","country_code","country_name","visitors","sessions","pageviews","enquirers"],"properties":{"city":{"type":"string","description":"The city’s name, e.g. `Pune`."},"region_name":{"type":["string","null"],"description":"The region it is in."},"country_code":{"type":"string","description":"ISO 3166-1 alpha-2 code of its country."},"country_name":{"type":["string","null"],"description":"Its country’s English name."},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors. A visitor is one browser: the same person on a phone and a laptop counts twice. Visitors with a session located in this city."},"sessions":{"type":"integer","minimum":0,"description":"Sessions located in this city."},"pageviews":{"type":"integer","minimum":0,"description":"Page views in those sessions."},"enquirers":{"type":"integer","minimum":0,"description":"Visitors who, in a session located in this city, sent a form or reached a thank-you (confirmation) page."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"city":"Delhi","region_name":"Delhi","country_code":"IN","country_name":"India","visitors":700,"sessions":950,"pageviews":3010,"enquirers":18},{"city":"Dubai","region_name":"Dubai","country_code":"AE","country_name":"United Arab Emirates","visitors":300,"sessions":390,"pageviews":1250,"enquirers":9}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","country":null,"limit":100}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/events":{"get":{"operationId":"listStatsEvents","summary":"Events by name","description":"Every kind of event recorded in the range, with how often and by how many people. `limit`: 100 rows by default, at most 1000.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"The event names.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"Every kind of event recorded in the range, most frequent first.","items":{"type":"object","description":"One event name.","required":["event_name","events","visitors"],"properties":{"event_name":{"type":"string","description":"The event, e.g. `pageview`, `section_viewed`, `outbound_click`, `form_submit`."},"events":{"type":"integer","minimum":0,"description":"Times it was recorded."},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors. A visitor is one browser: the same person on a phone and a laptop counts twice. Visitors who recorded it."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"event_name":"section_viewed","events":48210,"visitors":6120},{"event_name":"pageview","events":31260,"visitors":9120},{"event_name":"form_submit","events":701,"visitors":612}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","limit":100}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/funnel":{"get":{"operationId":"getStatsFunnel","summary":"How many people did steps in order","description":"For a sequence of events, how many visitors did each step and all the steps before it, in that order, within 7 days of their first step. `meta.query.window_days` states the window. Steps are event names (GET /v1/stats/events lists them). `utm_campaign` and `utm_source` narrow it to one campaign or one source code, following every event of the people who carried that tag at least once in the range — a sequence counted per tagged event would manufacture the drop-off it is meant to report. Those figures therefore will not tie with the same campaign on GET /v1/stats/overview, by design; the parameters explain why.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/UtmCampaign"},{"$ref":"#/components/parameters/UtmSource"},{"name":"steps","in":"query","required":true,"description":"Event names in the order they must happen, separated by commas, e.g. `pageview,form_started,form_submit`. From 1 to 10 steps, each at most 200 characters.","schema":{"type":"string","example":"pageview,form_started,form_submit"}}],"responses":{"200":{"description":"One entry per step.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"One entry per step, in the order asked for.","items":{"type":"object","description":"One step.","required":["position","event_name","visitors","of_first_pct","of_previous_pct"],"properties":{"position":{"type":"integer","minimum":0,"description":"The step’s place in the funnel, from 1."},"event_name":{"type":"string","description":"The event this step waits for."},"visitors":{"type":"integer","minimum":0,"description":"Visitors who did this step and every step before it, in order, within 7 days of the first step. The first step must fall in the range."},"of_first_pct":{"type":["number","null"],"description":"`visitors` as a percentage of the first step’s, 0–100, one decimal."},"of_previous_pct":{"type":["number","null"],"description":"`visitors` as a percentage of the step before, one decimal. null on step 1."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"position":1,"event_name":"pageview","visitors":9120,"of_first_pct":100,"of_previous_pct":null},{"position":2,"event_name":"form_started","visitors":910,"of_first_pct":10,"of_previous_pct":10},{"position":3,"event_name":"form_submit","visitors":540,"of_first_pct":5.9,"of_previous_pct":59.3}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","utm_campaign":null,"utm_source":null,"steps":["pageview","form_started","form_submit"],"window_days":7}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/forms":{"get":{"operationId":"listStatsForms","summary":"How each page’s form is doing","description":"One entry per page carrying a registration or application form (FormCrafts or SEED’s own), following visitors from opening the page to the thank-you page. Read the flags before the rates: `submissions_reporting` false means the form is not reporting, not that nobody registered, and `blind_confirmations` counts registrations the form missed. Sign-in and newsletter boxes are not counted. `limit`: 100 rows by default, at most 1000. `utm_campaign` and `utm_source` narrow it to one campaign or one source code, following every event of the people who carried that tag at least once in the range — a sequence counted per tagged event would manufacture the drop-off it is meant to report. Those figures therefore will not tie with the same campaign on GET /v1/stats/overview, by design; the parameters explain why.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/UtmCampaign"},{"$ref":"#/components/parameters/UtmSource"},{"$ref":"#/components/parameters/Limit"}],"responses":{"200":{"description":"The pages with forms.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"Pages carrying a form, most viewers first. Each page is followed through five stages, each a count of distinct visitors: viewers → reached → started → submitters → confirmed.","items":{"type":"object","description":"One page with a form.","required":["path","title","site","provider","form_type","form_name","viewers","reached","started","submitters","submissions","confirmed","total_form_seconds","median_form_seconds","engaged_not_converted","abandoned","blind_confirmations","reach_rate_pct","start_rate_pct","submit_rate_pct","submissions_reporting","reach_measured","starts_measured"],"properties":{"path":{"type":"string","description":"The page the form sits on. Any email address in it is shown as `redacted`."},"title":{"type":["string","null"],"description":"The page title most visitors saw, without the \" — SEED Global Education\" suffix. Any email address in it is shown as `redacted`."},"site":{"type":"string","description":"The page’s website, as a hostname without `www.`."},"provider":{"type":["string","null"],"description":"Which form system most submitters used: `formcrafts` or `seed`. null with no submissions."},"form_type":{"type":["string","null"],"description":"The kind of form, e.g. `masterclass` or `smu-day`, when the form reports one."},"form_name":{"type":["string","null"],"description":"The name of the form most submitters used."},"viewers":{"type":"integer","minimum":0,"description":"Stage 1: visitors who opened the page."},"reached":{"type":"integer","minimum":0,"description":"Stage 2: visitors who scrolled the form into view."},"started":{"type":"integer","minimum":0,"description":"Stage 3: visitors who began typing in the form. 0 on pages whose form does not report this; see `starts_measured`."},"submitters":{"type":"integer","minimum":0,"description":"Stage 4: visitors who sent the form."},"submissions":{"type":"integer","minimum":0,"description":"Times the form was sent. Above `submitters` when people send it twice."},"confirmed":{"type":"integer","minimum":0,"description":"Stage 5: visitors who reached the page’s thank-you page."},"total_form_seconds":{"type":"number","description":"Seconds all visitors together spent on the form section, one decimal."},"median_form_seconds":{"type":["number","null"],"description":"Median seconds one submitter spent on the form section, one decimal. null when no submitter’s time was recorded."},"engaged_not_converted":{"type":"integer","minimum":0,"description":"Visitors who spent 45 seconds or more on the form and then neither sent it nor reached the thank-you page."},"abandoned":{"type":["integer","null"],"minimum":0,"description":"Visitors who began typing and never sent the form. null when starts are not measured."},"blind_confirmations":{"type":"integer","minimum":0,"description":"Thank-you page visitors beyond those who sent the form: registrations the form did not report. Watch this one: a rise means a form has stopped reporting."},"reach_rate_pct":{"type":["number","null"],"description":"`reached` as a percentage of `viewers`, 0–100, one decimal. null with no viewers."},"start_rate_pct":{"type":["number","null"],"description":"`started` as a percentage of `reached`. null when either stage is not measured on this page."},"submit_rate_pct":{"type":["number","null"],"description":"`submitters` as a percentage of `reached`. null when there is no measurable `reached`, or the page is not reporting submissions."},"submissions_reporting":{"type":"boolean","description":"False when the page has confirmations but no recorded submissions: the form is not reporting, so read its zero as missing data, not as nobody registering."},"reach_measured":{"type":"boolean","description":"False when the page’s form section cannot stand for the form (it is unnamed, or fewer people reached it than sent the form), so `reached` and the rates built on it are not meaningful."},"starts_measured":{"type":"boolean","description":"False when the form does not report people beginning to type."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"path":"/study-abroad/events/virtual/masterclass/example-university","title":"Example University Masterclass","site":"seedglobaleducation.com","provider":"formcrafts","form_type":"masterclass","form_name":"Masterclass registration","viewers":2104,"reached":1310,"started":702,"submitters":602,"submissions":625,"confirmed":590,"total_form_seconds":48210.4,"median_form_seconds":102.6,"engaged_not_converted":64,"abandoned":100,"blind_confirmations":0,"reach_rate_pct":62.3,"start_rate_pct":53.6,"submit_rate_pct":46,"submissions_reporting":true,"reach_measured":true,"starts_measured":true},{"path":"/study-abroad/events/in-person/example-city","title":"In-person event","site":"seedglobaleducation.com","provider":null,"form_type":null,"form_name":null,"viewers":880,"reached":410,"started":0,"submitters":0,"submissions":0,"confirmed":96,"total_form_seconds":9120,"median_form_seconds":null,"engaged_not_converted":22,"abandoned":null,"blind_confirmations":96,"reach_rate_pct":46.6,"start_rate_pct":null,"submit_rate_pct":null,"submissions_reporting":false,"reach_measured":true,"starts_measured":false}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","utm_campaign":null,"utm_source":null,"limit":100}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/form-dropoff":{"get":{"operationId":"getStatsFormDropoff","summary":"Where the in-house forms lose people","description":"SEED’s own multi-page forms (the scholarship application, the course-finder questionnaire), all together: how many began and finished, which page people stopped on and which field they last answered. Field answers are never recorded or returned. `forms` lists each form with data in the range; GET /v1/stats/forms/{form_id} narrows to one. `utm_campaign` and `utm_source` narrow it to one campaign or one source code, following every event of the people who carried that tag at least once in the range — a sequence counted per tagged event would manufacture the drop-off it is meant to report. Those figures therefore will not tie with the same campaign on GET /v1/stats/overview, by design; the parameters explain why.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/UtmCampaign"},{"$ref":"#/components/parameters/UtmSource"}],"responses":{"200":{"description":"Drop-off for every in-house form together.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","description":"Where an in-house form loses people: by page of the form, and by field.","required":["form_id","form_name","started","submitted","abandoned","completion_pct","forms","steps","fields"],"properties":{"form_id":{"type":["string","null"],"description":"The form, or null for every in-house form together."},"form_name":{"type":["string","null"],"description":"Its name. null for every form together."},"started":{"type":"integer","minimum":0,"description":"Visitors who began the form."},"submitted":{"type":"integer","minimum":0,"description":"Visitors who sent it."},"abandoned":{"type":"integer","minimum":0,"description":"Visitors the form recorded giving up."},"completion_pct":{"type":["number","null"],"description":"`submitted` as a percentage of `started`, 0–100, one decimal. null when nobody started."},"forms":{"type":"array","description":"Every in-house form with data in the range, most starts first. Use `form_id` with GET /v1/stats/forms/{form_id}.","items":{"type":"object","description":"One form.","required":["form_id","form_name","started"],"properties":{"form_id":{"type":"string","description":"The form’s id."},"form_name":{"type":["string","null"],"description":"The form’s name."},"started":{"type":"integer","minimum":0,"description":"Visitors who began it."}}}},"steps":{"type":"array","description":"The form’s pages, in order.","items":{"type":"object","description":"One page of the form.","required":["step","step_name","reached","stopped_here"],"properties":{"step":{"type":"integer","minimum":0,"description":"The page number, from 1."},"step_name":{"type":["string","null"],"description":"The page’s title, e.g. `About you`."},"reached":{"type":"integer","minimum":0,"description":"Visitors who were on this page at some point."},"stopped_here":{"type":"integer","minimum":0,"description":"Visitors whose last recorded page was this one and who gave up."}}}},"fields":{"type":"array","description":"The form’s fields, in the order they appear.","items":{"type":"object","description":"One field. Never its answers: only who reached it.","required":["field_id","field_label","position","step","filled","dropped_after","dropout_pct","abandoned_in","errored"],"properties":{"field_id":{"type":"string","description":"The field’s id, e.g. `first_name`."},"field_label":{"type":["string","null"],"description":"The label shown beside it, e.g. `First name`."},"position":{"type":"integer","minimum":0,"description":"Its place in the form, from 0."},"step":{"type":"integer","minimum":0,"description":"The page of the form it is on."},"filled":{"type":"integer","minimum":0,"description":"Visitors who answered it."},"dropped_after":{"type":"integer","minimum":0,"description":"Visitors whose last answer was this field, and who never sent the form."},"dropout_pct":{"type":"number","description":"`dropped_after` as a percentage of `filled`, 0–100, one decimal. 0 when nobody filled it."},"abandoned_in":{"type":"integer","minimum":0,"description":"Visitors whose cursor was in this field when they gave up."},"errored":{"type":"integer","minimum":0,"description":"Visitors shown a validation message on this field."}}}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":{"form_id":null,"form_name":null,"started":277,"submitted":98,"abandoned":170,"completion_pct":35.4,"forms":[{"form_id":"sc-boston-questrom","form_name":"Boston University Questrom Deans Award","started":180},{"form_id":"sc-asu-carey","form_name":"Arizona State W. P. Carey Award","started":97}],"steps":[{"step":1,"step_name":"About you","reached":277,"stopped_here":34},{"step":2,"step_name":"Academic background","reached":214,"stopped_here":71}],"fields":[{"field_id":"first_name","field_label":"First name","position":0,"step":1,"filled":277,"dropped_after":6,"dropout_pct":2.2,"abandoned_in":0,"errored":0},{"field_id":"email","field_label":"Email address","position":2,"step":1,"filled":259,"dropped_after":9,"dropout_pct":3.5,"abandoned_in":4,"errored":11}]},"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","utm_campaign":"open_day_delhi","utm_source":null}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/forms/{form_id}":{"get":{"operationId":"getStatsFormDropoffById","summary":"Where one in-house form loses people","description":"The same as GET /v1/stats/form-dropoff for one form. `forms` still lists every form with data, so one request can drive a form picker. An id with nothing recorded in the range answers with zeros. `utm_campaign` and `utm_source` narrow it to one campaign or one source code, following every event of the people who carried that tag at least once in the range — a sequence counted per tagged event would manufacture the drop-off it is meant to report. Those figures therefore will not tie with the same campaign on GET /v1/stats/overview, by design; the parameters explain why.","tags":["Stats"],"x-scope":"stats","parameters":[{"name":"form_id","in":"path","required":true,"description":"The in-house form, as `forms[].form_id` in GET /v1/stats/form-dropoff lists it.","schema":{"type":"string","maxLength":200,"example":"sc-boston-questrom"}},{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"$ref":"#/components/parameters/UtmCampaign"},{"$ref":"#/components/parameters/UtmSource"}],"responses":{"200":{"description":"Drop-off for one form.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","description":"Where an in-house form loses people: by page of the form, and by field.","required":["form_id","form_name","started","submitted","abandoned","completion_pct","forms","steps","fields"],"properties":{"form_id":{"type":["string","null"],"description":"The form, or null for every in-house form together."},"form_name":{"type":["string","null"],"description":"Its name. null for every form together."},"started":{"type":"integer","minimum":0,"description":"Visitors who began the form."},"submitted":{"type":"integer","minimum":0,"description":"Visitors who sent it."},"abandoned":{"type":"integer","minimum":0,"description":"Visitors the form recorded giving up."},"completion_pct":{"type":["number","null"],"description":"`submitted` as a percentage of `started`, 0–100, one decimal. null when nobody started."},"forms":{"type":"array","description":"Every in-house form with data in the range, most starts first. Use `form_id` with GET /v1/stats/forms/{form_id}.","items":{"type":"object","description":"One form.","required":["form_id","form_name","started"],"properties":{"form_id":{"type":"string","description":"The form’s id."},"form_name":{"type":["string","null"],"description":"The form’s name."},"started":{"type":"integer","minimum":0,"description":"Visitors who began it."}}}},"steps":{"type":"array","description":"The form’s pages, in order.","items":{"type":"object","description":"One page of the form.","required":["step","step_name","reached","stopped_here"],"properties":{"step":{"type":"integer","minimum":0,"description":"The page number, from 1."},"step_name":{"type":["string","null"],"description":"The page’s title, e.g. `About you`."},"reached":{"type":"integer","minimum":0,"description":"Visitors who were on this page at some point."},"stopped_here":{"type":"integer","minimum":0,"description":"Visitors whose last recorded page was this one and who gave up."}}}},"fields":{"type":"array","description":"The form’s fields, in the order they appear.","items":{"type":"object","description":"One field. Never its answers: only who reached it.","required":["field_id","field_label","position","step","filled","dropped_after","dropout_pct","abandoned_in","errored"],"properties":{"field_id":{"type":"string","description":"The field’s id, e.g. `first_name`."},"field_label":{"type":["string","null"],"description":"The label shown beside it, e.g. `First name`."},"position":{"type":"integer","minimum":0,"description":"Its place in the form, from 0."},"step":{"type":"integer","minimum":0,"description":"The page of the form it is on."},"filled":{"type":"integer","minimum":0,"description":"Visitors who answered it."},"dropped_after":{"type":"integer","minimum":0,"description":"Visitors whose last answer was this field, and who never sent the form."},"dropout_pct":{"type":"number","description":"`dropped_after` as a percentage of `filled`, 0–100, one decimal. 0 when nobody filled it."},"abandoned_in":{"type":"integer","minimum":0,"description":"Visitors whose cursor was in this field when they gave up."},"errored":{"type":"integer","minimum":0,"description":"Visitors shown a validation message on this field."}}}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":{"form_id":"sc-boston-questrom","form_name":"Boston University Questrom Deans Award","started":180,"submitted":64,"abandoned":116,"completion_pct":35.6,"forms":[{"form_id":"sc-boston-questrom","form_name":"Boston University Questrom Deans Award","started":180},{"form_id":"sc-asu-carey","form_name":"Arizona State W. P. Carey Award","started":97}],"steps":[{"step":1,"step_name":"About you","reached":180,"stopped_here":22},{"step":2,"step_name":"Academic background","reached":141,"stopped_here":48}],"fields":[{"field_id":"first_name","field_label":"First name","position":0,"step":1,"filled":180,"dropped_after":4,"dropout_pct":2.2,"abandoned_in":0,"errored":0}]},"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","utm_campaign":null,"utm_source":null,"form_id":"sc-boston-questrom"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/entities":{"get":{"operationId":"listStatsEntities","summary":"Page views per school","description":"Page views and visitors for each school (more kinds of entity may follow), optionally split by the visitor’s country or by how their session arrived. A view is one page view whose URL names the school and whose path starts with `path_prefix`. The school is identified by the id resolved from the URL slug when the view was recorded, or — if that failed — by the id the slug resolves to now; views whose slug resolves to no id are listed under the slug with `entity_id` null. `meta.query.slug_map_size` is how many slugs could be resolved now (0 means only ids resolved at the time count). Splits are per session, from its first event in the range: utm tags and referrers fall away after the landing page, so a per-view reading would credit most views to `internal` or nothing. Not narrowed by `utm_campaign` / `utm_source`; split by them instead.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"name":"entity","in":"query","required":false,"description":"What to count views of. Only `school` exists today; other kinds may be added.","schema":{"type":"string","enum":["school"],"default":"school"}},{"name":"entity_ids","in":"query","required":false,"description":"Only these entities, as SEED ids (for schools, the UDP school id) separated by commas, e.g. `101,205`. At most 1000. Default: every entity with a view in the range. A view counts for an id when the id was resolved from its URL slug, at the time or now (see the operation description); combine with `entity_slugs` to also catch views whose slug no id is known for. Long lists can exceed the URL length a proxy accepts (about 8 KB): split them over several requests.","schema":{"type":"string","example":"101,205"}},{"name":"entity_slugs","in":"query","required":false,"description":"Only these entities, by the URL slug the page was opened under, separated by commas, e.g. `kogod-school-of-business`. Lower-cased before matching; at most 1000. With `entity_ids` as well, an entity matching either is kept.","schema":{"type":"string","example":"kogod-school-of-business"}},{"name":"group_by","in":"query","required":false,"description":"Split each entity’s views into `groups`. `none` (default) leaves `groups` empty. `country` is where the session was (ISO code, as GET /v1/stats/countries); `referrer` the website the session came from (as GET /v1/stats/referrers); `utm_source`, `utm_medium`, `utm_campaign` the session’s tags (as GET /v1/stats/campaigns); `channel` the derived channel (`direct`, `organic_search`, `paid_social`, `referral`, …). Every split is taken from the session’s first event in the range, not from the page view itself.","schema":{"type":"string","enum":["none","country","referrer","utm_source","utm_medium","utm_campaign","channel"],"default":"none"}},{"name":"path_prefix","in":"query","required":false,"description":"Count only pages whose path starts with this. Default for `school`: `/study-abroad/`, which covers the school profile, its programme pages and its school-specific event pages. Must start with `/`.","schema":{"type":"string","maxLength":200,"example":"/study-abroad/"}},{"name":"page_type","in":"query","required":false,"description":"Count only these kinds of page, separated by commas, e.g. `school` for the profile alone or `school,program` for the profile and its programmes. Default: every kind under `path_prefix`.","schema":{"type":"string","example":"school"}},{"name":"limit","in":"query","required":false,"description":"Groups per entity, a whole number of at least 1: 20 by default, at most 100 (a larger value is lowered to 100). Does not limit the entities, of which at most 1000 are listed.","schema":{"type":"integer","minimum":1,"default":20}}],"responses":{"200":{"description":"The entities, each with its split.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"One entry per entity with at least one view in the range, most views first, at most 1000.","items":{"type":"object","description":"One entity.","required":["entity_id","entity_slug","views","visitors","groups"],"properties":{"entity_id":{"type":["string","null"],"description":"The SEED id (for a school, the UDP school id), as a string. null when no id is known for the slug the pages were opened under — the entry then stands for that slug alone."},"entity_slug":{"type":["string","null"],"description":"The URL slug of the most recent view. Slugs follow the display name and change when it is renamed, so use `entity_id` as the key."},"views":{"type":"integer","minimum":0,"description":"Page views of this entity’s pages in the range."},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors. A visitor is one browser: the same person on a phone and a laptop counts twice. Visitors who viewed any of this entity’s pages."},"groups":{"type":"array","description":"The split asked for with `group_by`, most views first, at most `limit` entries. Empty when `group_by` is `none`. Groups do not add up to `visitors`, since one visitor can be in several.","items":{"type":"object","description":"One group.","required":["key","label","views","visitors"],"properties":{"key":{"type":["string","null"],"description":"The group: an ISO 3166-1 alpha-2 code for `country`, a hostname for `referrer`, the tag for the `utm_*` splits, the channel name for `channel`. null for sessions with no value: not located, no referrer (direct), untagged, or recorded before channels were stored. Any email address in it is shown as `redacted`."},"label":{"type":["string","null"],"description":"A readable name for `key` where one exists: the country name for `country`; otherwise null."},"views":{"type":"integer","minimum":0,"description":"Page views of this entity in sessions of this group."},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors of this entity in sessions of this group."}}}}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"entity_id":"101","entity_slug":"kogod-school-of-business","views":1840,"visitors":1210,"groups":[{"key":"IN","label":"India","views":1102,"visitors":730},{"key":"AE","label":"United Arab Emirates","views":214,"visitors":150},{"key":null,"label":null,"views":380,"visitors":260}]},{"entity_id":null,"entity_slug":"new-school-not-yet-in-udp","views":12,"visitors":9,"groups":[{"key":"IN","label":"India","views":12,"visitors":9}]}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"human","entity":"school","entity_ids":null,"entity_slugs":null,"group_by":"country","path_prefix":"/study-abroad/","page_type":null,"limit":20,"max_entities":1000,"slug_map_size":707}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/stats/bots":{"get":{"operationId":"getStatsBots","summary":"Automated traffic","description":"How much of the traffic was software rather than people (search engines, AI crawlers, monitors), and of which kind. Always counts both sides, so `bots` is ignored and `meta.query.bots` says `all`. Automated visits are flagged by their user agent and kept out of every other figure by default.","tags":["Stats"],"x-scope":"stats","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"}],"responses":{"200":{"description":"The split and its kinds.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","description":"Both sides of the split between people and automated traffic, whatever `bots` says.","required":["human_events","bot_events","total_events","bot_events_pct","human_visitors","bot_visitors","human_sessions","bot_sessions","by_kind"],"properties":{"human_events":{"type":"integer","minimum":0,"description":"Events from people."},"bot_events":{"type":"integer","minimum":0,"description":"Events from software we recognised: search engines, AI crawlers, monitors."},"total_events":{"type":"integer","minimum":0,"description":"Both together."},"bot_events_pct":{"type":["number","null"],"description":"`bot_events` as a percentage of `total_events`, 0–100, one decimal. null with no events."},"human_visitors":{"type":"integer","minimum":0,"description":"Distinct visitors among people."},"bot_visitors":{"type":"integer","minimum":0,"description":"Distinct automated visitors."},"human_sessions":{"type":"integer","minimum":0,"description":"Sessions among people."},"bot_sessions":{"type":"integer","minimum":0,"description":"Automated sessions."},"by_kind":{"type":"array","description":"Automated traffic by kind, most events first.","items":{"type":"object","description":"One kind of software.","required":["kind","events","visitors"],"properties":{"kind":{"type":["string","null"],"description":"`search`, `ai`, `seo`, `social`, `monitor`, `tool` or `other`."},"events":{"type":"integer","minimum":0,"description":"Events of this kind."},"visitors":{"type":"integer","minimum":0,"description":"Distinct visitors of this kind (approximate)."}}}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":{"human_events":88410,"bot_events":12030,"total_events":100440,"bot_events_pct":12,"human_visitors":9120,"bot_visitors":2210,"human_sessions":12840,"bot_sessions":2290,"by_kind":[{"kind":"ai","events":6205,"visitors":1203},{"kind":"search","events":5190,"visitors":886}]},"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"from":"2026-08-23","to":"2026-09-21","site":"seedglobaleducation.com","bots":"all"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/catalogue/pages":{"get":{"operationId":"listCataloguePages","summary":"Pages and how many sections they carry","description":"Every page whose sections we know, one entry per page, ordered by site and then path. Pages report their own `data-sa-section` markers when visited; nothing crawls the site, so a page appears after its first visit. This is the pages’ current state, not a count over time: `from`, `to` and `bots` do not apply and are ignored. The catalogue holds no automated traffic and nothing personal. `site` still applies. Paginated: `limit` is 100 by default and at most 1000; pass `meta.pagination.next_cursor` back as `cursor` for the next page, with the same other parameters.","tags":["Catalogue"],"x-scope":"catalogue","parameters":[{"$ref":"#/components/parameters/Site"},{"name":"q","in":"query","required":false,"description":"Only pages whose path contains this text, ignoring case, e.g. `scholarship`.","schema":{"type":"string","maxLength":2048,"example":"scholarship"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"The pages, ordered by site and then path.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"The pages, ordered by site and then path.","items":{"type":"object","description":"One page that has reported its sections.","required":["site","site_id","path","page_type","live_sections","total_sections","last_reported_at"],"properties":{"site":{"type":["string","null"],"description":"The website, as the hostname `?site=` takes. null for a site that is not one of SEED’s known sites."},"site_id":{"type":"string","description":"Our internal site id: `b2c`, `finder` or `finder_legacy`."},"path":{"type":"string","description":"The page’s path, e.g. `/study-abroad/usa`. Pass it as `path` to GET /v1/catalogue/sections."},"page_type":{"type":["string","null"],"description":"What kind of page it is, e.g. `home` or `event_detail`, from its latest report."},"live_sections":{"type":"integer","minimum":0,"description":"Sections the page still carries: seen within 24 hours of its latest report."},"total_sections":{"type":"integer","minimum":0,"description":"Every section the page has ever reported, live or gone."},"last_reported_at":{"type":"string","format":"date-time","description":"When a visitor’s browser last reported this page’s sections, ISO 8601 UTC. A page nobody visits stops reporting, so an old time means an unvisited page, not an empty one."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"site":"seedglobaleducation.com","site_id":"b2c","path":"/","page_type":"home","live_sections":18,"total_sections":19,"last_reported_at":"2026-09-21T10:20:03Z"},{"site":"seedglobaleducation.com","site_id":"b2c","path":"/study-abroad/scholarships","page_type":"scholarship_list","live_sections":3,"total_sections":3,"last_reported_at":"2026-09-20T18:12:09Z"}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"site":"seedglobaleducation.com","q":null,"limit":2},"pagination":{"limit":2,"next_cursor":"eyJrIjpbImIyYyIsIi9zdHVkeS1hYnJvYWQvc2Nob2xhcnNoaXBzIl19","has_more":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/catalogue/sections":{"get":{"operationId":"listCatalogueSections","summary":"The sections of a page","description":"The sections a page carries, top to bottom, each with its name, where it sits and whether it is still there. Without `path`, the sections of every page, ordered by site, page, live first and position. This is the pages’ current state, not a count over time: `from`, `to` and `bots` do not apply and are ignored. The catalogue holds no automated traffic and nothing personal. `site` still applies. Paginated: `limit` is 100 by default and at most 1000; pass `meta.pagination.next_cursor` back as `cursor` for the next page, with the same other parameters.","tags":["Catalogue"],"x-scope":"catalogue","parameters":[{"$ref":"#/components/parameters/Site"},{"name":"path","in":"query","required":false,"description":"One page, e.g. `/study-abroad/usa`. Must start with `/`. Tidied the way the collector tidies paths, so `/Study-Abroad/USA/` finds `/study-abroad/usa`. Default: the sections of every page.","schema":{"type":"string","maxLength":2048,"example":"/study-abroad/usa"}},{"name":"live","in":"query","required":false,"description":"`true` for live sections only: those the page still carried in its latest reports. Default `false` lists sections that have since gone as well, with `is_live` false.","schema":{"type":"boolean","default":false}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"The sections, top to bottom.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"The sections, top to bottom.","items":{"type":"object","description":"One section of one page.","required":["site","site_id","path","section_id","label","parent_section_id","depth","display_order","is_live","first_seen_at","last_seen_at","sightings"],"properties":{"site":{"type":["string","null"],"description":"The website, as the hostname `?site=` takes. null for a site that is not one of SEED’s known sites."},"site_id":{"type":"string","description":"Our internal site id: `b2c`, `finder` or `finder_legacy`."},"path":{"type":"string","description":"The page it is on."},"section_id":{"type":"string","description":"The section’s marker, its `data-sa-section` value, e.g. `hero` or `scholarships`. The same word `section_id` means on GET /v1/stats/sections, before renames."},"label":{"type":["string","null"],"description":"The name shown for it (its `data-sa-label`, or its heading), latest first. null when it has none."},"parent_section_id":{"type":["string","null"],"description":"The section it sits inside, or null for a top-level one."},"depth":{"type":"integer","minimum":0,"description":"How deeply it is nested: 0 at the top level."},"display_order":{"type":"integer","minimum":0,"description":"Its place on the page as last reported; smaller is higher up."},"is_live":{"type":"boolean","description":"True when the page’s latest reports still carry it (seen within 24 hours of the page’s newest report). False for a section that has been removed."},"first_seen_at":{"type":"string","format":"date-time","description":"When it was first reported on this page, ISO 8601 UTC."},"last_seen_at":{"type":"string","format":"date-time","description":"When it was last reported on this page, ISO 8601 UTC."},"sightings":{"type":"integer","minimum":0,"description":"How many visits reported it on this page."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"site":"seedglobaleducation.com","site_id":"b2c","path":"/","section_id":"hero","label":"Home landing page","parent_section_id":null,"depth":0,"display_order":1,"is_live":true,"first_seen_at":"2026-09-21T09:00:00Z","last_seen_at":"2026-09-21T10:20:03Z","sightings":42},{"site":"seedglobaleducation.com","site_id":"b2c","path":"/","section_id":"stats","label":"Headline numbers strip","parent_section_id":null,"depth":0,"display_order":2,"is_live":true,"first_seen_at":"2026-09-21T09:00:00Z","last_seen_at":"2026-09-21T10:20:03Z","sightings":42}],"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z","query":{"site":"seedglobaleducation.com","path":"/","live":false,"limit":100},"pagination":{"limit":100,"next_cursor":null,"has_more":false}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/events":{"get":{"operationId":"listEvents","summary":"List events","description":"Every recorded event, oldest first, one row per event. Order is (time, id) — id breaks ties at the same millisecond, so pages never skip or repeat a row. Page with meta.pagination.next_cursor; a cursor is only valid with the same filters (dates may be omitted on later pages — the cursor carries them). visitor_id matches every id of a merged person. Personal fields (ip_address, user_agent, contact_id, personal-looking property keys) appear only with personal data access. Events that arrive late with an earlier time than your cursor will not appear on later pages; an incremental sync should re-read its last few minutes. Default limit 100, maximum 1000.","tags":["Events"],"x-scope":"events","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"name":"event","in":"query","required":false,"description":"Only this event name, e.g. pageview, section_viewed, outbound_click, form_submit.","schema":{"type":"string"}},{"name":"path","in":"query","required":false,"description":"Only this exact page path, e.g. /study-abroad/scholarships.","schema":{"type":"string"}},{"name":"visitor_id","in":"query","required":false,"description":"Only this visitor — any of their ids; merged visitors come back whole.","schema":{"type":"string"}},{"name":"session_id","in":"query","required":false,"description":"Only this session id.","schema":{"type":"string"}},{"name":"page_type","in":"query","required":false,"description":"Only this page type, e.g. program, school, scholarship_detail.","schema":{"type":"string"}},{"name":"country","in":"query","required":false,"description":"Only events located in this country: ISO 3166-1 alpha-2 in capitals, e.g. IN.","schema":{"type":"string","pattern":"^[A-Z]{2}$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"One page of events.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"Events, oldest first.","items":{"type":"object","description":"One recorded event.","required":["id","name","time","visitor_id","raw_visitor_id","session_id","site","path","url","title","page_type","referrer","referrer_domain","channel","utm","click_ids","device","location","bot","consent_state","is_identified","school","program","properties"],"properties":{"id":{"type":"string","description":"Event id (UUID). Unique per row; the tiebreak of the list order.","format":"uuid"},"name":{"type":"string","description":"Event name, e.g. pageview, section_viewed, outbound_click, form_submit, finder_results."},"time":{"type":"string","description":"When the event happened (the browser's clock). ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"visitor_id":{"type":"string","description":"Canonical visitor id: the same person across our sites. Use this to join to /v1/visitors."},"raw_visitor_id":{"type":"string","description":"The visitor id the browser actually sent. Differs from visitor_id only for a merged visitor."},"session_id":{"type":["string","null"],"description":"Session id as recorded by the tracker."},"site":{"type":["string","null"],"description":"Hostname the event was recorded on, as recorded (www. kept), e.g. seedglobaleducation.com."},"path":{"type":["string","null"],"description":"Page path, with per-person segments redacted at ingest."},"url":{"type":["string","null"],"description":"Full page URL (path redacted as above; the query string is kept)."},"title":{"type":["string","null"],"description":"document.title as recorded. Often the PREVIOUS page for an SPA pageview; the journey endpoint shows the corrected name."},"page_type":{"type":["string","null"],"description":"Page category, e.g. program, school, scholarship_detail, finder_results."},"referrer":{"type":["string","null"],"description":"document.referrer as recorded."},"referrer_domain":{"type":["string","null"],"description":"Hostname of the referrer, www. stripped."},"channel":{"type":["string","null"],"description":"Acquisition channel derived at ingest: direct, organic_search, paid_search, organic_social, paid_social, email, referral, affiliate, influencer, internal or unknown."},"utm":{"type":"object","description":"Campaign parameters from the page URL.","required":["source","medium","campaign","term","content"],"properties":{"source":{"type":["string","null"],"description":"utm_source. Opaque campaign codes such as SEED309 are common."},"medium":{"type":["string","null"],"description":"utm_medium."},"campaign":{"type":["string","null"],"description":"utm_campaign."},"term":{"type":["string","null"],"description":"utm_term."},"content":{"type":["string","null"],"description":"utm_content."}}},"click_ids":{"type":"object","description":"Ad click ids from the page URL.","required":["gclid","fbclid"],"properties":{"gclid":{"type":["string","null"],"description":"Google Ads click id."},"fbclid":{"type":["string","null"],"description":"Meta click id."}}},"device":{"type":"object","description":"Parsed from the user agent.","required":["type","browser","browser_version","os"],"properties":{"type":{"type":["string","null"],"description":"desktop, mobile, tablet, bot or unknown."},"browser":{"type":["string","null"],"description":"Browser name; in-app browsers (Instagram, LinkedIn) are named as such."},"browser_version":{"type":["string","null"],"description":"Browser version."},"os":{"type":["string","null"],"description":"Operating system."}}},"location":{"type":"object","description":"Where the event was sent from. Every field is null when the row was never located.","required":["country_code","country","region_code","region","city","timezone","isp","org","asn","is_mobile_network","is_proxy","is_hosting","source"],"properties":{"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 country code, e.g. IN."},"country":{"type":["string","null"],"description":"Country name, e.g. India."},"region_code":{"type":["string","null"],"description":"The lookup provider's region code, e.g. MH."},"region":{"type":["string","null"],"description":"Region name, e.g. Maharashtra."},"city":{"type":["string","null"],"description":"City name."},"timezone":{"type":["string","null"],"description":"IANA time zone, e.g. Asia/Kolkata."},"isp":{"type":["string","null"],"description":"Internet provider, from the IP lookup."},"org":{"type":["string","null"],"description":"Organisation owning the address, from the IP lookup."},"asn":{"type":["integer","null"],"description":"Autonomous system number, from the IP lookup."},"is_mobile_network":{"type":["boolean","null"],"description":"The connection is a mobile carrier (not the same as the device being a phone). null unless source is ip-api."},"is_proxy":{"type":["boolean","null"],"description":"The address is a known proxy or VPN. null unless source is ip-api."},"is_hosting":{"type":["boolean","null"],"description":"The address belongs to a hosting provider. null unless source is ip-api."},"source":{"type":["string","null"],"description":"How the location was found: ip-api (live lookup), apache-log (backfilled), none (looked up, no answer), or null (never looked up — every row before 15 Sep 2026)."}}},"bot":{"type":"object","description":"Crawler classification from the user agent. Bots are flagged, never dropped.","required":["is_bot","kind"],"properties":{"is_bot":{"type":"boolean","description":"True for a crawler or tool."},"kind":{"type":["string","null"],"description":"search, ai, seo, social, monitor, tool or other."}}},"consent_state":{"type":["string","null"],"description":"Consent at capture: granted, denied, not_asked or exempt."},"is_identified":{"type":"boolean","description":"The browser had been identified (signed in) when this event was sent."},"school":{"type":"object","description":"The school the page is about, when it is about one.","required":["id","slug"],"properties":{"id":{"type":["string","null"],"description":"School id."},"slug":{"type":["string","null"],"description":"School URL slug."}}},"program":{"type":"object","description":"The programme the page is about, when it is about one.","required":["id","slug"],"properties":{"id":{"type":["string","null"],"description":"Programme id."},"slug":{"type":["string","null"],"description":"Programme URL slug."}}},"properties":{"type":"object","additionalProperties":{"type":"string"},"description":"Event-specific properties, all as strings (e.g. section_id, section_label, active_ms on section_viewed; href, target_domain, link_text on outbound_click; form_id, form_name, form_provider on form events; query, count, filters, sort on finder_ events). Keys that could identify a person (matching /email|phone|mobile|whatsapp|^name$|first_?name|last_?name|full_?name|^ip$|address|passport|birth|^dob$|^contact_id$|^submission_id$/i) are removed unless the key has personal data access. `value` is always removed from the scholarship application (form_provider = seed). The course-finder questionnaire (form_provider = seed-quiz) keeps its answers in `value`."},"ip_address":{"type":["string","null"],"description":"The raw IP address the event came from (stored since 15 Sep 2026). Only with personal data access (a server key holding `people`); otherwise the field is absent.","x-personal-data":true},"user_agent":{"type":["string","null"],"description":"The full user agent string. Only with personal data access (a server key holding `people`); otherwise the field is absent.","x-personal-data":true},"contact_id":{"type":["string","null"],"description":"CRM contact id stamped on the event by a form submission. Only with personal data access (a server key holding `people`); otherwise the field is absent.","x-personal-data":true}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"id":"0d6f4c1a-7e2b-4a9c-b3d5-8f1e2a3b4c5d","name":"section_viewed","time":"2026-09-21T10:20:03.123Z","visitor_id":"5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","raw_visitor_id":"5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","session_id":"c3d9e1f0-6a2b-4d7c-8e5f-9a0b1c2d3e4f","site":"seedglobaleducation.com","path":"/study-abroad/scholarships","url":"https://seedglobaleducation.com/study-abroad/scholarships?utm_source=SEED309&utm_medium=email","title":"Scholarships — SEED Global Education","page_type":"scholarship_list","referrer":null,"referrer_domain":null,"channel":"email","utm":{"source":"SEED309","medium":"email","campaign":"sept-newsletter","term":null,"content":null},"click_ids":{"gclid":null,"fbclid":null},"device":{"type":"mobile","browser":"Instagram","browser_version":"350.0","os":"iOS"},"location":{"country_code":"IN","country":"India","region_code":"MH","region":"Maharashtra","city":"Pune","timezone":"Asia/Kolkata","isp":"Example Carrier","org":"Example Org","asn":64500,"is_mobile_network":true,"is_proxy":false,"is_hosting":false,"source":"ip-api"},"bot":{"is_bot":false,"kind":null},"consent_state":"granted","is_identified":true,"school":{"id":null,"slug":null},"program":{"id":null,"slug":null},"properties":{"section_id":"faq","section_label":"Frequently asked questions","section_index":"4","active_ms":"12840","visible_ms":"15000","max_ratio":"100"},"ip_address":"203.0.113.7","user_agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) Instagram 350.0","contact_id":"crm-000123"}],"meta":{"request_id":"req_01J8ZK3Q7X5W2V9T4R6N8M0P1B","generated_at":"2026-09-22T09:00:00.000Z","query":{"from":"2026-08-24","to":"2026-09-22","site":null,"bots":"human","event":"section_viewed","path":null,"visitor_id":null,"session_id":null,"page_type":null,"country":"IN"},"pagination":{"limit":100,"next_cursor":"eyJ2IjoxLCJ0IjoiMjAyNi0wOS0yMSAxMDoyMDowMy4xMjMiLCJpZCI6Ii4uLiJ9","has_more":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/events/{event_id}":{"get":{"operationId":"getEvent","summary":"Get one event","description":"One event by id, in the same shape as the list. Not limited by dates or by bots. A key restricted to some sites finds only events on those sites.","tags":["Events"],"x-scope":"events","parameters":[{"name":"event_id","in":"path","required":true,"description":"Event id (UUID) from /v1/events.","schema":{"type":"string","format":"uuid"}},{"name":"site","in":"query","required":false,"description":"Optional hostname. A key restricted to some sites reads only those; without ?site= the record is checked against all of them.","schema":{"type":"string"}}],"responses":{"200":{"description":"The event.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","description":"One recorded event.","required":["id","name","time","visitor_id","raw_visitor_id","session_id","site","path","url","title","page_type","referrer","referrer_domain","channel","utm","click_ids","device","location","bot","consent_state","is_identified","school","program","properties"],"properties":{"id":{"type":"string","description":"Event id (UUID). Unique per row; the tiebreak of the list order.","format":"uuid"},"name":{"type":"string","description":"Event name, e.g. pageview, section_viewed, outbound_click, form_submit, finder_results."},"time":{"type":"string","description":"When the event happened (the browser's clock). ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"visitor_id":{"type":"string","description":"Canonical visitor id: the same person across our sites. Use this to join to /v1/visitors."},"raw_visitor_id":{"type":"string","description":"The visitor id the browser actually sent. Differs from visitor_id only for a merged visitor."},"session_id":{"type":["string","null"],"description":"Session id as recorded by the tracker."},"site":{"type":["string","null"],"description":"Hostname the event was recorded on, as recorded (www. kept), e.g. seedglobaleducation.com."},"path":{"type":["string","null"],"description":"Page path, with per-person segments redacted at ingest."},"url":{"type":["string","null"],"description":"Full page URL (path redacted as above; the query string is kept)."},"title":{"type":["string","null"],"description":"document.title as recorded. Often the PREVIOUS page for an SPA pageview; the journey endpoint shows the corrected name."},"page_type":{"type":["string","null"],"description":"Page category, e.g. program, school, scholarship_detail, finder_results."},"referrer":{"type":["string","null"],"description":"document.referrer as recorded."},"referrer_domain":{"type":["string","null"],"description":"Hostname of the referrer, www. stripped."},"channel":{"type":["string","null"],"description":"Acquisition channel derived at ingest: direct, organic_search, paid_search, organic_social, paid_social, email, referral, affiliate, influencer, internal or unknown."},"utm":{"type":"object","description":"Campaign parameters from the page URL.","required":["source","medium","campaign","term","content"],"properties":{"source":{"type":["string","null"],"description":"utm_source. Opaque campaign codes such as SEED309 are common."},"medium":{"type":["string","null"],"description":"utm_medium."},"campaign":{"type":["string","null"],"description":"utm_campaign."},"term":{"type":["string","null"],"description":"utm_term."},"content":{"type":["string","null"],"description":"utm_content."}}},"click_ids":{"type":"object","description":"Ad click ids from the page URL.","required":["gclid","fbclid"],"properties":{"gclid":{"type":["string","null"],"description":"Google Ads click id."},"fbclid":{"type":["string","null"],"description":"Meta click id."}}},"device":{"type":"object","description":"Parsed from the user agent.","required":["type","browser","browser_version","os"],"properties":{"type":{"type":["string","null"],"description":"desktop, mobile, tablet, bot or unknown."},"browser":{"type":["string","null"],"description":"Browser name; in-app browsers (Instagram, LinkedIn) are named as such."},"browser_version":{"type":["string","null"],"description":"Browser version."},"os":{"type":["string","null"],"description":"Operating system."}}},"location":{"type":"object","description":"Where the event was sent from. Every field is null when the row was never located.","required":["country_code","country","region_code","region","city","timezone","isp","org","asn","is_mobile_network","is_proxy","is_hosting","source"],"properties":{"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 country code, e.g. IN."},"country":{"type":["string","null"],"description":"Country name, e.g. India."},"region_code":{"type":["string","null"],"description":"The lookup provider's region code, e.g. MH."},"region":{"type":["string","null"],"description":"Region name, e.g. Maharashtra."},"city":{"type":["string","null"],"description":"City name."},"timezone":{"type":["string","null"],"description":"IANA time zone, e.g. Asia/Kolkata."},"isp":{"type":["string","null"],"description":"Internet provider, from the IP lookup."},"org":{"type":["string","null"],"description":"Organisation owning the address, from the IP lookup."},"asn":{"type":["integer","null"],"description":"Autonomous system number, from the IP lookup."},"is_mobile_network":{"type":["boolean","null"],"description":"The connection is a mobile carrier (not the same as the device being a phone). null unless source is ip-api."},"is_proxy":{"type":["boolean","null"],"description":"The address is a known proxy or VPN. null unless source is ip-api."},"is_hosting":{"type":["boolean","null"],"description":"The address belongs to a hosting provider. null unless source is ip-api."},"source":{"type":["string","null"],"description":"How the location was found: ip-api (live lookup), apache-log (backfilled), none (looked up, no answer), or null (never looked up — every row before 15 Sep 2026)."}}},"bot":{"type":"object","description":"Crawler classification from the user agent. Bots are flagged, never dropped.","required":["is_bot","kind"],"properties":{"is_bot":{"type":"boolean","description":"True for a crawler or tool."},"kind":{"type":["string","null"],"description":"search, ai, seo, social, monitor, tool or other."}}},"consent_state":{"type":["string","null"],"description":"Consent at capture: granted, denied, not_asked or exempt."},"is_identified":{"type":"boolean","description":"The browser had been identified (signed in) when this event was sent."},"school":{"type":"object","description":"The school the page is about, when it is about one.","required":["id","slug"],"properties":{"id":{"type":["string","null"],"description":"School id."},"slug":{"type":["string","null"],"description":"School URL slug."}}},"program":{"type":"object","description":"The programme the page is about, when it is about one.","required":["id","slug"],"properties":{"id":{"type":["string","null"],"description":"Programme id."},"slug":{"type":["string","null"],"description":"Programme URL slug."}}},"properties":{"type":"object","additionalProperties":{"type":"string"},"description":"Event-specific properties, all as strings (e.g. section_id, section_label, active_ms on section_viewed; href, target_domain, link_text on outbound_click; form_id, form_name, form_provider on form events; query, count, filters, sort on finder_ events). Keys that could identify a person (matching /email|phone|mobile|whatsapp|^name$|first_?name|last_?name|full_?name|^ip$|address|passport|birth|^dob$|^contact_id$|^submission_id$/i) are removed unless the key has personal data access. `value` is always removed from the scholarship application (form_provider = seed). The course-finder questionnaire (form_provider = seed-quiz) keeps its answers in `value`."},"ip_address":{"type":["string","null"],"description":"The raw IP address the event came from (stored since 15 Sep 2026). Only with personal data access (a server key holding `people`); otherwise the field is absent.","x-personal-data":true},"user_agent":{"type":["string","null"],"description":"The full user agent string. Only with personal data access (a server key holding `people`); otherwise the field is absent.","x-personal-data":true},"contact_id":{"type":["string","null"],"description":"CRM contact id stamped on the event by a form submission. Only with personal data access (a server key holding `people`); otherwise the field is absent.","x-personal-data":true}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":{"id":"0d6f4c1a-7e2b-4a9c-b3d5-8f1e2a3b4c5d","name":"section_viewed","time":"2026-09-21T10:20:03.123Z","visitor_id":"5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","raw_visitor_id":"5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","session_id":"c3d9e1f0-6a2b-4d7c-8e5f-9a0b1c2d3e4f","site":"seedglobaleducation.com","path":"/study-abroad/scholarships","url":"https://seedglobaleducation.com/study-abroad/scholarships?utm_source=SEED309&utm_medium=email","title":"Scholarships — SEED Global Education","page_type":"scholarship_list","referrer":null,"referrer_domain":null,"channel":"email","utm":{"source":"SEED309","medium":"email","campaign":"sept-newsletter","term":null,"content":null},"click_ids":{"gclid":null,"fbclid":null},"device":{"type":"mobile","browser":"Instagram","browser_version":"350.0","os":"iOS"},"location":{"country_code":"IN","country":"India","region_code":"MH","region":"Maharashtra","city":"Pune","timezone":"Asia/Kolkata","isp":"Example Carrier","org":"Example Org","asn":64500,"is_mobile_network":true,"is_proxy":false,"is_hosting":false,"source":"ip-api"},"bot":{"is_bot":false,"kind":null},"consent_state":"granted","is_identified":true,"school":{"id":null,"slug":null},"program":{"id":null,"slug":null},"properties":{"section_id":"faq","section_label":"Frequently asked questions","section_index":"4","active_ms":"12840","visible_ms":"15000","max_ratio":"100"},"ip_address":"203.0.113.7","user_agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) Instagram 350.0","contact_id":"crm-000123"},"meta":{"request_id":"req_01J8ZK3Q7X5W2V9T4R6N8M0P1B","generated_at":"2026-09-22T09:00:00.000Z"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/visitors":{"get":{"operationId":"listVisitors","summary":"List visitors","description":"Visitors with activity in the range, most recent activity first. One row per PERSON: ids merged across our sites are one row under the canonical visitor_id. The first page fixes a snapshot (meta.query.as_of); later pages of the same listing read only data ingested by then, so a visitor active while you page does not move. With a site, the figures describe that site only. `person` appears only with personal data access. Default limit 100, maximum 1000.","tags":["Visitors"],"x-scope":"visitors","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"name":"identified","in":"query","required":false,"description":"true: only visitors who signed in during the range. false: only those who did not.","schema":{"type":"boolean"}},{"name":"country","in":"query","required":false,"description":"Only visitors with at least one event located in this country (ISO 3166-1 alpha-2, capitals).","schema":{"type":"string","pattern":"^[A-Z]{2}$"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"One page of visitors.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"Visitors, most recent activity first.","items":{"type":"object","description":"One visitor (person) with activity in the range.","required":["visitor_id","first_seen","last_seen","events","pageviews","sessions","visits","is_identified","location","device","first_source","linked_ids"],"properties":{"visitor_id":{"type":"string","description":"Canonical visitor id: one person, merged across our sites."},"first_seen":{"type":"string","description":"First event in the range. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"last_seen":{"type":"string","description":"Latest event in the range. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"events":{"type":"integer","description":"Events in the range."},"pageviews":{"type":"integer","description":"Pageviews in the range."},"sessions":{"type":"integer","description":"Distinct recorded session ids. Before Sep 2026 each browser tab had its own, so this over-counts older history; see visits."},"visits":{"type":"integer","description":"Visits by the 30-minute-silence rule the dashboard uses (the corrected session count)."},"is_identified":{"type":"boolean","description":"Any event in the range was sent after the visitor signed in."},"location":{"type":["object","null"],"description":"Where they were most recently, from the latest located event. null when nothing was located.","required":["country_code","country","region_code","region","city","timezone"],"properties":{"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 country code, e.g. IN."},"country":{"type":["string","null"],"description":"Country name, e.g. India."},"region_code":{"type":["string","null"],"description":"The lookup provider's region code, e.g. MH."},"region":{"type":["string","null"],"description":"Region name, e.g. Maharashtra."},"city":{"type":["string","null"],"description":"City name."},"timezone":{"type":["string","null"],"description":"IANA time zone, e.g. Asia/Kolkata."}}},"device":{"type":"object","description":"Device of their latest event.","required":["type","browser","os"],"properties":{"type":{"type":["string","null"],"description":"desktop, mobile, tablet, bot or unknown."},"browser":{"type":["string","null"],"description":"Browser name."},"os":{"type":["string","null"],"description":"Operating system."}}},"first_source":{"type":"object","description":"How they arrived: their first event in the range.","required":["site","landing_path","referrer_domain","channel","utm_source","utm_medium","utm_campaign"],"properties":{"site":{"type":["string","null"],"description":"Hostname they landed on."},"landing_path":{"type":["string","null"],"description":"Path they landed on."},"referrer_domain":{"type":["string","null"],"description":"Referrer hostname."},"channel":{"type":["string","null"],"description":"Acquisition channel."},"utm_source":{"type":["string","null"],"description":"utm_source."},"utm_medium":{"type":["string","null"],"description":"utm_medium."},"utm_campaign":{"type":["string","null"],"description":"utm_campaign."}}},"linked_ids":{"type":"array","description":"Every raw visitor id whose events are counted here, ascending. Length > 1 means a merged person.","items":{"type":"string","description":"Raw visitor id."}},"person":{"type":["object","null"],"description":"Who the visitor is, from sign-in (identify) and CRM form submissions. null when neither is known. Only with personal data access (a server key holding `people`); otherwise the field is absent.","required":["name","email","phone","person_key","contact_id"],"properties":{"name":{"type":["string","null"],"description":"Name sent at sign-in.","x-personal-data":true},"email":{"type":["string","null"],"description":"Email sent at sign-in.","x-personal-data":true},"phone":{"type":["string","null"],"description":"Phone number sent at sign-in.","x-personal-data":true},"person_key":{"type":["string","null"],"description":"The key the site identified the person by (its CRM contact id).","x-personal-data":true},"contact_id":{"type":["string","null"],"description":"Latest CRM contact id stamped on any of their events.","x-personal-data":true}},"x-personal-data":true}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"visitor_id":"5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","first_seen":"2026-09-02T08:11:20.450Z","last_seen":"2026-09-21T10:31:09.870Z","events":212,"pageviews":31,"sessions":9,"visits":7,"is_identified":true,"location":{"country_code":"IN","country":"India","region_code":"MH","region":"Maharashtra","city":"Pune","timezone":"Asia/Kolkata"},"device":{"type":"mobile","browser":"Instagram","os":"iOS"},"first_source":{"site":"seedglobaleducation.com","landing_path":"/","referrer_domain":"instagram.com","channel":"organic_social","utm_source":null,"utm_medium":null,"utm_campaign":null},"linked_ids":["5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","b7e14d2c-8a3f-4e5b-9c6d-1f2a3b4c5d6e"],"person":{"name":"Ada Lovelace","email":"ada@example.com","phone":"+91 00000 00000","person_key":"crm-000123","contact_id":"crm-000123"}}],"meta":{"request_id":"req_01J8ZK3Q7X5W2V9T4R6N8M0P1B","generated_at":"2026-09-22T09:00:00.000Z","query":{"from":"2026-08-24","to":"2026-09-22","site":null,"bots":"human","identified":null,"country":null,"as_of":"2026-09-22T09:00:00.000Z"},"pagination":{"limit":100,"next_cursor":"eyJ2IjoxLCJ0IjoiMjAyNi0wOS0yMSAxMDoyMDowMy4xMjMiLCJpZCI6Ii4uLiJ9","has_more":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/visitors/{visitor_id}":{"get":{"operationId":"getVisitor","summary":"Get one visitor","description":"One visitor over the range — any of their ids answers, under the canonical visitor_id — with their latest 20 sessions. 404 when they have no events in the range; error.details.reason = outside_range (with first_seen/last_seen) means they exist but not in these dates.","tags":["Visitors"],"x-scope":"visitors","parameters":[{"name":"visitor_id","in":"path","required":true,"description":"Any visitor id of the person.","schema":{"type":"string"}},{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"}],"responses":{"200":{"description":"The visitor.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","description":"One visitor over the range, with their latest sessions.","required":["visitor_id","first_seen","last_seen","events","pageviews","sessions","visits","is_identified","location","device","first_source","linked_ids","recent_sessions"],"properties":{"visitor_id":{"type":"string","description":"Canonical visitor id: one person, merged across our sites."},"first_seen":{"type":"string","description":"First event in the range. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"last_seen":{"type":"string","description":"Latest event in the range. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"events":{"type":"integer","description":"Events in the range."},"pageviews":{"type":"integer","description":"Pageviews in the range."},"sessions":{"type":"integer","description":"Distinct recorded session ids. Before Sep 2026 each browser tab had its own, so this over-counts older history; see visits."},"visits":{"type":"integer","description":"Visits by the 30-minute-silence rule the dashboard uses (the corrected session count)."},"is_identified":{"type":"boolean","description":"Any event in the range was sent after the visitor signed in."},"location":{"type":["object","null"],"description":"Where they were most recently, from the latest located event. null when nothing was located.","required":["country_code","country","region_code","region","city","timezone"],"properties":{"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 country code, e.g. IN."},"country":{"type":["string","null"],"description":"Country name, e.g. India."},"region_code":{"type":["string","null"],"description":"The lookup provider's region code, e.g. MH."},"region":{"type":["string","null"],"description":"Region name, e.g. Maharashtra."},"city":{"type":["string","null"],"description":"City name."},"timezone":{"type":["string","null"],"description":"IANA time zone, e.g. Asia/Kolkata."}}},"device":{"type":"object","description":"Device of their latest event.","required":["type","browser","os"],"properties":{"type":{"type":["string","null"],"description":"desktop, mobile, tablet, bot or unknown."},"browser":{"type":["string","null"],"description":"Browser name."},"os":{"type":["string","null"],"description":"Operating system."}}},"first_source":{"type":"object","description":"How they arrived: their first event in the range.","required":["site","landing_path","referrer_domain","channel","utm_source","utm_medium","utm_campaign"],"properties":{"site":{"type":["string","null"],"description":"Hostname they landed on."},"landing_path":{"type":["string","null"],"description":"Path they landed on."},"referrer_domain":{"type":["string","null"],"description":"Referrer hostname."},"channel":{"type":["string","null"],"description":"Acquisition channel."},"utm_source":{"type":["string","null"],"description":"utm_source."},"utm_medium":{"type":["string","null"],"description":"utm_medium."},"utm_campaign":{"type":["string","null"],"description":"utm_campaign."}}},"linked_ids":{"type":"array","description":"Every raw visitor id whose events are counted here, ascending. Length > 1 means a merged person.","items":{"type":"string","description":"Raw visitor id."}},"person":{"type":["object","null"],"description":"Who the visitor is, from sign-in (identify) and CRM form submissions. null when neither is known. Only with personal data access (a server key holding `people`); otherwise the field is absent.","required":["name","email","phone","person_key","contact_id"],"properties":{"name":{"type":["string","null"],"description":"Name sent at sign-in.","x-personal-data":true},"email":{"type":["string","null"],"description":"Email sent at sign-in.","x-personal-data":true},"phone":{"type":["string","null"],"description":"Phone number sent at sign-in.","x-personal-data":true},"person_key":{"type":["string","null"],"description":"The key the site identified the person by (its CRM contact id).","x-personal-data":true},"contact_id":{"type":["string","null"],"description":"Latest CRM contact id stamped on any of their events.","x-personal-data":true}},"x-personal-data":true},"recent_sessions":{"type":"array","description":"Their latest 20 sessions in the range, newest first.","items":{"type":"object","description":"One session id as the tracker recorded it, folded from its events in the range.","required":["session_id","visitor_id","raw_visitor_id","started_at","ended_at","duration_seconds","events","pageviews","entry_path","site","utm_source","country_code","device_type"],"properties":{"session_id":{"type":"string","description":"Session id."},"visitor_id":{"type":"string","description":"Canonical visitor id of the session."},"raw_visitor_id":{"type":"string","description":"The visitor id on the session’s first event, as the browser sent it."},"started_at":{"type":"string","description":"First event of the session in the range. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"ended_at":{"type":"string","description":"Last event of the session in the range. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"duration_seconds":{"type":"number","description":"ended_at minus started_at, in seconds (1 decimal). 0 for a one-event session."},"events":{"type":"integer","description":"Events in the session."},"pageviews":{"type":"integer","description":"Pageviews in the session."},"entry_path":{"type":["string","null"],"description":"Path of the first event — the landing page."},"site":{"type":["string","null"],"description":"Hostname of the first event."},"utm_source":{"type":["string","null"],"description":"utm_source on the first event."},"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 of the first located event; null when nothing in the session was located."},"device_type":{"type":["string","null"],"description":"Device type of the first event."}}}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":{"visitor_id":"5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","first_seen":"2026-09-02T08:11:20.450Z","last_seen":"2026-09-21T10:31:09.870Z","events":212,"pageviews":31,"sessions":9,"visits":7,"is_identified":true,"location":{"country_code":"IN","country":"India","region_code":"MH","region":"Maharashtra","city":"Pune","timezone":"Asia/Kolkata"},"device":{"type":"mobile","browser":"Instagram","os":"iOS"},"first_source":{"site":"seedglobaleducation.com","landing_path":"/","referrer_domain":"instagram.com","channel":"organic_social","utm_source":null,"utm_medium":null,"utm_campaign":null},"linked_ids":["5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","b7e14d2c-8a3f-4e5b-9c6d-1f2a3b4c5d6e"],"person":{"name":"Ada Lovelace","email":"ada@example.com","phone":"+91 00000 00000","person_key":"crm-000123","contact_id":"crm-000123"},"recent_sessions":[{"session_id":"c3d9e1f0-6a2b-4d7c-8e5f-9a0b1c2d3e4f","visitor_id":"5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","raw_visitor_id":"5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","started_at":"2026-09-21T10:18:41.002Z","ended_at":"2026-09-21T10:31:09.870Z","duration_seconds":748.9,"events":37,"pageviews":5,"entry_path":"/study-abroad/scholarships","site":"seedglobaleducation.com","utm_source":"SEED309","country_code":"IN","device_type":"mobile"}]},"meta":{"request_id":"req_01J8ZK3Q7X5W2V9T4R6N8M0P1B","generated_at":"2026-09-22T09:00:00.000Z","query":{"from":"2026-08-24","to":"2026-09-22","site":null,"bots":"human"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/visitors/{visitor_id}/journey":{"get":{"operationId":"getVisitorJourney","summary":"Get a visitor journey","description":"The same journey the dashboard shows: everything the person did in the range, in order, across all their ids, with how they arrived, the strongest thing they did, per-visit location and whole-range totals. Humans only (bots is always human). The timeline stops at 500 steps (truncated = true); the summary still covers everything. With a site (named, or the key's only site) the steps and totals cover that site only. `person` and visits[].network.ip_address appear only with personal data access.","tags":["Visitors"],"x-scope":"visitors","parameters":[{"name":"visitor_id","in":"path","required":true,"description":"Any visitor id of the person.","schema":{"type":"string"}},{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"}],"responses":{"200":{"description":"The journey.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","description":"One visitor’s journey over the range: the dashboard’s timeline, in contract form.","required":["visitor_id","linked_ids","is_identified","truncated","entry","exit","device","location","outcome","summary","visits","steps"],"properties":{"visitor_id":{"type":"string","description":"Canonical visitor id (any of the person’s ids answers with this one)."},"linked_ids":{"type":"array","description":"Raw visitor ids whose events are in the timeline, ascending.","items":{"type":"string","description":"Raw visitor id."}},"is_identified":{"type":"boolean","description":"Signed in at some point in the range."},"person":{"type":["object","null"],"description":"Who the visitor is, from sign-in (identify) and CRM form submissions. null when neither is known. Only with personal data access (a server key holding `people`); otherwise the field is absent.","required":["name","email","phone","person_key","contact_id"],"properties":{"name":{"type":["string","null"],"description":"Name sent at sign-in.","x-personal-data":true},"email":{"type":["string","null"],"description":"Email sent at sign-in.","x-personal-data":true},"phone":{"type":["string","null"],"description":"Phone number sent at sign-in.","x-personal-data":true},"person_key":{"type":["string","null"],"description":"The key the site identified the person by (its CRM contact id).","x-personal-data":true},"contact_id":{"type":["string","null"],"description":"Latest CRM contact id stamped on any of their events.","x-personal-data":true}},"x-personal-data":true},"truncated":{"type":"boolean","description":"The timeline was cut at 500 steps (the earliest are kept); the summary still covers everything."},"entry":{"type":"object","description":"How they arrived: the first event.","required":["site","path","title","referrer_domain","channel","utm_source","utm_medium","utm_campaign"],"properties":{"site":{"type":["string","null"],"description":"Hostname."},"path":{"type":["string","null"],"description":"Landing path."},"title":{"type":["string","null"],"description":"Landing page title as recorded."},"referrer_domain":{"type":["string","null"],"description":"Referrer hostname."},"channel":{"type":["string","null"],"description":"Acquisition channel."},"utm_source":{"type":["string","null"],"description":"utm_source."},"utm_medium":{"type":["string","null"],"description":"utm_medium."},"utm_campaign":{"type":["string","null"],"description":"utm_campaign."}}},"exit":{"type":"object","description":"Where they ended up: the last event.","required":["path","title"],"properties":{"path":{"type":["string","null"],"description":"Path."},"title":{"type":["string","null"],"description":"Title as recorded."}}},"device":{"type":"object","description":"Device of the first event.","required":["type","browser","os"],"properties":{"type":{"type":["string","null"],"description":"Device type."},"browser":{"type":["string","null"],"description":"Browser."},"os":{"type":["string","null"],"description":"Operating system."}}},"location":{"type":["object","null"],"description":"Where they were: the first located event in the range. null when nothing was located.","required":["country_code","country","region_code","region","city","timezone"],"properties":{"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 country code, e.g. IN."},"country":{"type":["string","null"],"description":"Country name, e.g. India."},"region_code":{"type":["string","null"],"description":"The lookup provider's region code, e.g. MH."},"region":{"type":["string","null"],"description":"Region name, e.g. Maharashtra."},"city":{"type":["string","null"],"description":"City name."},"timezone":{"type":["string","null"],"description":"IANA time zone, e.g. Asia/Kolkata."}}},"outcome":{"type":"object","description":"The strongest thing they did.","required":["type","detail","form_page_title","click_domain"],"properties":{"type":{"type":"string","description":"form: submitted a form. form_unfinished: started or typed into a form without submitting. click: clicked out to another site (links to our own sites do not count). browsed: saw more than one page. bounced: one page.","enum":["form","form_unfinished","click","browsed","bounced"]},"detail":{"type":["string","null"],"description":"The form’s name, or the link’s text, behind the outcome. Often null for older form submissions."},"form_page_title":{"type":["string","null"],"description":"Title of the page the submitted form sat on."},"click_domain":{"type":["string","null"],"description":"Where the outcome click went."}}},"summary":{"type":"object","description":"Totals over the whole range — never over the truncated steps.","required":["events","pageviews","visits","forms_submitted","form_fields_filled","pages","sites","first_seen","last_seen","section_seconds","page_seconds"],"properties":{"events":{"type":"integer","description":"Events."},"pageviews":{"type":"integer","description":"Pageviews."},"visits":{"type":"integer","description":"Visits (30-minute-silence rule)."},"forms_submitted":{"type":"integer","description":"Forms submitted."},"form_fields_filled":{"type":"integer","description":"Form fields filled in (re-answering counts again)."},"pages":{"type":"integer","description":"Distinct pages (site + path)."},"sites":{"type":"integer","description":"Distinct hostnames (www. counted separately)."},"first_seen":{"type":["string","null"],"description":"First event. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"last_seen":{"type":["string","null"],"description":"Last event. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"section_seconds":{"type":"number","description":"Active seconds on measured page sections, summed. Not time on site: sections can nest or not cover a page."},"page_seconds":{"type":"number","description":"Active seconds on pages, from page exits — the honest time-on-site figure."}}},"visits":{"type":"array","description":"One entry per visit, in order.","items":{"type":"object","description":"One visit of the journey (30-minute-silence rule) and where it came from.","required":["visit","session_id","started_at","location_source","location","network","ip_count","country_changed","previous_country"],"properties":{"visit":{"type":"integer","description":"1-based visit number; matches steps[].visit."},"session_id":{"type":["string","null"],"description":"Session id on the visit’s first step."},"started_at":{"type":"string","description":"The visit's first step. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"location_source":{"type":["string","null"],"description":"ip-api or apache-log when located; none when looked up without an answer; null when never looked up."},"location":{"type":["object","null"],"description":"Where the visitor was, from an IP lookup that answered (geo source ip-api or apache-log). null when nothing in the range was located.","required":["country_code","country","region_code","region","city","timezone"],"properties":{"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 country code, e.g. IN."},"country":{"type":["string","null"],"description":"Country name, e.g. India."},"region_code":{"type":["string","null"],"description":"The lookup provider's region code, e.g. MH."},"region":{"type":["string","null"],"description":"Region name, e.g. Maharashtra."},"city":{"type":["string","null"],"description":"City name."},"timezone":{"type":["string","null"],"description":"IANA time zone, e.g. Asia/Kolkata."}}},"network":{"type":["object","null"],"description":"The connection, from the same lookup that located the visit. null when not located.","required":["isp","org","asn","is_mobile_network","is_proxy","is_hosting"],"properties":{"isp":{"type":["string","null"],"description":"Internet provider."},"org":{"type":["string","null"],"description":"Organisation owning the address."},"asn":{"type":["integer","null"],"description":"Autonomous system number."},"is_mobile_network":{"type":["boolean","null"],"description":"Mobile carrier connection. null unless located by ip-api."},"is_proxy":{"type":["boolean","null"],"description":"Proxy or VPN. null unless located by ip-api."},"is_hosting":{"type":["boolean","null"],"description":"Hosting provider. null unless located by ip-api."},"ip_address":{"type":["string","null"],"description":"The raw IP address of that lookup. Only with personal data access (a server key holding `people`); otherwise the field is absent.","x-personal-data":true}}},"ip_count":{"type":"integer","description":"Distinct IP addresses seen during the visit (more than one: Wi-Fi to mobile, or a VPN)."},"country_changed":{"type":"boolean","description":"Located in a different country from the nearest earlier located visit."},"previous_country":{"type":["string","null"],"description":"That earlier country, when country_changed."}}}},"steps":{"type":"array","description":"The timeline, oldest first (at most 500).","items":{"type":"object","description":"One step of the timeline, in the order it happened.","required":["time","type","event","visit","session_id","is_entry","page","section","detail","action","reason","destination_domain","cta_id","duration_seconds","scroll_pct","finder"],"properties":{"time":{"type":"string","description":"When it happened. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"type":{"type":"string","description":"What kind of step. pageview: opened a page. page_exit: left a page (its time is also on the pageview). section: a part of the page was on screen. click: followed a link (outbound_click). cta: pressed a marked call-to-action button. form: started, answered, moved through, errored on, abandoned or submitted a form. search: typed into a catalogue search box. finder: results, filters, sorting, paging, scrolling or opening a school/programme in the course finder or an event directory. article: jumped within an article. profile_gate: hit a sign-in wall on a profile. booking: a step of booking a call. consent: withdrew cookie consent. other: anything newer.","enum":["pageview","page_exit","section","click","cta","form","search","finder","article","profile_gate","booking","consent","other"]},"event":{"type":"string","description":"The raw event name, e.g. form_field_filled."},"visit":{"type":"integer","description":"Which visit (1-based, 30-minute-silence rule) this step belongs to; matches visits[].visit."},"session_id":{"type":["string","null"],"description":"Session id recorded on the row."},"is_entry":{"type":"boolean","description":"The first step of the journey (the one `entry` describes)."},"page":{"type":"object","description":"The page it happened on.","required":["site","path","title"],"properties":{"site":{"type":["string","null"],"description":"Hostname."},"path":{"type":["string","null"],"description":"Path."},"title":{"type":["string","null"],"description":"The name most visitors saw for this page (corrected for stale SPA titles)."}}},"section":{"type":["object","null"],"description":"For section steps: the band on the page. For cta steps: the band the button sat in (id only). null otherwise.","required":["id","label","index"],"properties":{"id":{"type":["string","null"],"description":"Section id (a slug such as hero or faq)."},"label":{"type":["string","null"],"description":"The heading the band carried on screen."},"index":{"type":["integer","null"],"description":"Position down the page, 0 at the top."}}},"detail":{"type":["string","null"],"description":"The one most useful string for the step: section id; link text (else destination) for a click; button text for a cta; form name for form_started/form_submit; field label (plus the answer for the course-finder questionnaire) for form_field_filled; step name for form_step; the last question for form_abandoned; search text; result count; the facet that moved; the programme and school; scroll depth; article heading; profile part; booking slot."},"action":{"type":["string","null"],"description":"The verb where the event carries one, e.g. save, open, apply, resumed."},"reason":{"type":["string","null"],"description":"Why a form was abandoned: page_hidden, unmounted, left_the_finder."},"destination_domain":{"type":["string","null"],"description":"Where a click went (hostname), including our own sites."},"cta_id":{"type":["string","null"],"description":"The authored id of the button pressed (cta steps)."},"duration_seconds":{"type":["number","null"],"description":"Section steps: seconds this band was actively on screen in this flush (a fragment of its total). Pageview steps: active seconds on that page, from the exit that closed it; null when no exit arrived. null for every other step."},"scroll_pct":{"type":["integer","null"],"description":"Pageview steps: how far down the page they got, 0–100. null when no exit arrived, and on other steps."},"finder":{"type":["object","null"],"description":"Course-finder and directory context (finder and search steps only; null otherwise).","required":["catalogue","sort","direction","query","filters","changed_to","initial"],"properties":{"catalogue":{"type":["string","null"],"description":"Which list: schools, prime, xpress, events-in-person, events-virtual."},"sort":{"type":["string","null"],"description":"The sort in force, as the page labels it."},"direction":{"type":["string","null"],"description":"asc or desc (sort steps)."},"query":{"type":["string","null"],"description":"Search text in the box (scrubbed of emails and long digit runs by the site)."},"filters":{"type":"array","description":"Names (not values) of the filters in force.","items":{"type":"string","description":"Filter name."}},"changed_to":{"type":["string","null"],"description":"What the moved facets were set to: name=value; name=value (filter steps)."},"initial":{"type":"boolean","description":"The first result set of a freshly opened catalogue, not an answer to anything the visitor did."}}}}}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":{"visitor_id":"5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","linked_ids":["5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","b7e14d2c-8a3f-4e5b-9c6d-1f2a3b4c5d6e"],"is_identified":true,"person":{"name":"Ada Lovelace","email":"ada@example.com","phone":"+91 00000 00000","person_key":"crm-000123","contact_id":"crm-000123"},"truncated":false,"entry":{"site":"seedglobaleducation.com","path":"/study-abroad/scholarships","title":"Scholarships — SEED Global Education","referrer_domain":null,"channel":"email","utm_source":"SEED309","utm_medium":"email","utm_campaign":"sept-newsletter"},"exit":{"path":"/programs-prime","title":"Course Finder — SEED Global Education"},"device":{"type":"mobile","browser":"Instagram","os":"iOS"},"location":{"country_code":"IN","country":"India","region_code":"MH","region":"Maharashtra","city":"Pune","timezone":"Asia/Kolkata"},"outcome":{"type":"form_unfinished","detail":"SeedPrime questionnaire","form_page_title":null,"click_domain":null},"summary":{"events":37,"pageviews":5,"visits":1,"forms_submitted":0,"form_fields_filled":6,"pages":4,"sites":2,"first_seen":"2026-09-21T10:18:41.002Z","last_seen":"2026-09-21T10:31:09.870Z","section_seconds":183.4,"page_seconds":402.7},"visits":[{"visit":1,"session_id":"c3d9e1f0-6a2b-4d7c-8e5f-9a0b1c2d3e4f","started_at":"2026-09-21T10:18:41.002Z","location_source":"ip-api","location":{"country_code":"IN","country":"India","region_code":"MH","region":"Maharashtra","city":"Pune","timezone":"Asia/Kolkata"},"network":{"isp":"Example Carrier","org":"Example Org","asn":64500,"is_mobile_network":true,"is_proxy":false,"is_hosting":false,"ip_address":"203.0.113.7"},"ip_count":1,"country_changed":false,"previous_country":null}],"steps":[{"time":"2026-09-21T10:18:41.002Z","type":"pageview","event":"pageview","visit":1,"session_id":"c3d9e1f0-6a2b-4d7c-8e5f-9a0b1c2d3e4f","is_entry":true,"page":{"site":"seedglobaleducation.com","path":"/study-abroad/scholarships","title":"SEED Scholarships Fund — $10M+ in Awards"},"section":null,"detail":null,"action":null,"reason":null,"destination_domain":null,"cta_id":null,"duration_seconds":94.2,"scroll_pct":88,"finder":null},{"time":"2026-09-21T10:20:03.123Z","type":"section","event":"section_viewed","visit":1,"session_id":"c3d9e1f0-6a2b-4d7c-8e5f-9a0b1c2d3e4f","is_entry":false,"page":{"site":"seedglobaleducation.com","path":"/study-abroad/scholarships","title":"SEED Scholarships Fund — $10M+ in Awards"},"section":{"id":"faq","label":"Frequently asked questions","index":4},"detail":"faq","action":null,"reason":null,"destination_domain":null,"cta_id":null,"duration_seconds":12.8,"scroll_pct":null,"finder":null},{"time":"2026-09-21T10:27:15.400Z","type":"finder","event":"finder_results","visit":1,"session_id":"e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b","is_entry":false,"page":{"site":"finder.seedglobaleducation.com","path":"/programs-prime","title":"Course Finder — SEED Global Education"},"section":null,"detail":"57","action":null,"reason":null,"destination_domain":null,"cta_id":null,"duration_seconds":null,"scroll_pct":null,"finder":{"catalogue":"prime","sort":"Match Score","direction":null,"query":"data science","filters":["country","intake"],"changed_to":null,"initial":false}}]},"meta":{"request_id":"req_01J8ZK3Q7X5W2V9T4R6N8M0P1B","generated_at":"2026-09-22T09:00:00.000Z","query":{"from":"2026-08-24","to":"2026-09-22","site":null,"bots":"human"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/sessions":{"get":{"operationId":"listSessions","summary":"List sessions","description":"Recorded session ids with activity in the range, newest first by start time (session_id breaks ties). Each is folded from its events, so entry_path is the true landing page. Before Sep 2026 the tracker made one session per browser tab, so older history has more sessions than visits. Default limit 100, maximum 1000.","tags":["Sessions"],"x-scope":"visitors","parameters":[{"$ref":"#/components/parameters/From"},{"$ref":"#/components/parameters/To"},{"$ref":"#/components/parameters/Site"},{"$ref":"#/components/parameters/Bots"},{"name":"visitor_id","in":"query","required":false,"description":"Only this visitor — any of their ids; merged visitors come back whole.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"One page of sessions.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"Sessions, newest first.","items":{"type":"object","description":"One session id as the tracker recorded it, folded from its events in the range.","required":["session_id","visitor_id","raw_visitor_id","started_at","ended_at","duration_seconds","events","pageviews","entry_path","site","utm_source","country_code","device_type"],"properties":{"session_id":{"type":"string","description":"Session id."},"visitor_id":{"type":"string","description":"Canonical visitor id of the session."},"raw_visitor_id":{"type":"string","description":"The visitor id on the session’s first event, as the browser sent it."},"started_at":{"type":"string","description":"First event of the session in the range. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"ended_at":{"type":"string","description":"Last event of the session in the range. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"duration_seconds":{"type":"number","description":"ended_at minus started_at, in seconds (1 decimal). 0 for a one-event session."},"events":{"type":"integer","description":"Events in the session."},"pageviews":{"type":"integer","description":"Pageviews in the session."},"entry_path":{"type":["string","null"],"description":"Path of the first event — the landing page."},"site":{"type":["string","null"],"description":"Hostname of the first event."},"utm_source":{"type":["string","null"],"description":"utm_source on the first event."},"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 of the first located event; null when nothing in the session was located."},"device_type":{"type":["string","null"],"description":"Device type of the first event."}}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"session_id":"c3d9e1f0-6a2b-4d7c-8e5f-9a0b1c2d3e4f","visitor_id":"5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","raw_visitor_id":"5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","started_at":"2026-09-21T10:18:41.002Z","ended_at":"2026-09-21T10:31:09.870Z","duration_seconds":748.9,"events":37,"pageviews":5,"entry_path":"/study-abroad/scholarships","site":"seedglobaleducation.com","utm_source":"SEED309","country_code":"IN","device_type":"mobile"}],"meta":{"request_id":"req_01J8ZK3Q7X5W2V9T4R6N8M0P1B","generated_at":"2026-09-22T09:00:00.000Z","query":{"from":"2026-08-24","to":"2026-09-22","site":null,"bots":"human","visitor_id":null},"pagination":{"limit":100,"next_cursor":"eyJ2IjoxLCJ0IjoiMjAyNi0wOS0yMSAxMDoyMDowMy4xMjMiLCJpZCI6Ii4uLiJ9","has_more":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/sessions/{session_id}":{"get":{"operationId":"getSession","summary":"Get one session","description":"One session and its events in order (at most 1000, same shape as /v1/events). Not limited by dates or by bots. A key restricted to some sites sees only those sites’ events.","tags":["Sessions"],"x-scope":"visitors","parameters":[{"name":"session_id","in":"path","required":true,"description":"Session id from /v1/sessions or an event row.","schema":{"type":"string"}},{"name":"site","in":"query","required":false,"description":"Optional hostname. A key restricted to some sites reads only those; without ?site= the record is checked against all of them.","schema":{"type":"string"}}],"responses":{"200":{"description":"The session.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","description":"One session and its events.","required":["session_id","visitor_id","raw_visitor_id","started_at","ended_at","duration_seconds","events","pageviews","entry_path","site","utm_source","country_code","device_type","events_truncated"],"properties":{"session_id":{"type":"string","description":"Session id."},"visitor_id":{"type":"string","description":"Canonical visitor id of the session."},"raw_visitor_id":{"type":"string","description":"The visitor id on the session’s first event, as the browser sent it."},"started_at":{"type":"string","description":"First event of the session in the range. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"ended_at":{"type":"string","description":"Last event of the session in the range. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"duration_seconds":{"type":"number","description":"ended_at minus started_at, in seconds (1 decimal). 0 for a one-event session."},"events":{"type":"array","description":"The session’s events in order (at most 1000), in the /v1/events row shape.","items":{"type":"object","description":"One recorded event.","required":["id","name","time","visitor_id","raw_visitor_id","session_id","site","path","url","title","page_type","referrer","referrer_domain","channel","utm","click_ids","device","location","bot","consent_state","is_identified","school","program","properties"],"properties":{"id":{"type":"string","description":"Event id (UUID). Unique per row; the tiebreak of the list order.","format":"uuid"},"name":{"type":"string","description":"Event name, e.g. pageview, section_viewed, outbound_click, form_submit, finder_results."},"time":{"type":"string","description":"When the event happened (the browser's clock). ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"visitor_id":{"type":"string","description":"Canonical visitor id: the same person across our sites. Use this to join to /v1/visitors."},"raw_visitor_id":{"type":"string","description":"The visitor id the browser actually sent. Differs from visitor_id only for a merged visitor."},"session_id":{"type":["string","null"],"description":"Session id as recorded by the tracker."},"site":{"type":["string","null"],"description":"Hostname the event was recorded on, as recorded (www. kept), e.g. seedglobaleducation.com."},"path":{"type":["string","null"],"description":"Page path, with per-person segments redacted at ingest."},"url":{"type":["string","null"],"description":"Full page URL (path redacted as above; the query string is kept)."},"title":{"type":["string","null"],"description":"document.title as recorded. Often the PREVIOUS page for an SPA pageview; the journey endpoint shows the corrected name."},"page_type":{"type":["string","null"],"description":"Page category, e.g. program, school, scholarship_detail, finder_results."},"referrer":{"type":["string","null"],"description":"document.referrer as recorded."},"referrer_domain":{"type":["string","null"],"description":"Hostname of the referrer, www. stripped."},"channel":{"type":["string","null"],"description":"Acquisition channel derived at ingest: direct, organic_search, paid_search, organic_social, paid_social, email, referral, affiliate, influencer, internal or unknown."},"utm":{"type":"object","description":"Campaign parameters from the page URL.","required":["source","medium","campaign","term","content"],"properties":{"source":{"type":["string","null"],"description":"utm_source. Opaque campaign codes such as SEED309 are common."},"medium":{"type":["string","null"],"description":"utm_medium."},"campaign":{"type":["string","null"],"description":"utm_campaign."},"term":{"type":["string","null"],"description":"utm_term."},"content":{"type":["string","null"],"description":"utm_content."}}},"click_ids":{"type":"object","description":"Ad click ids from the page URL.","required":["gclid","fbclid"],"properties":{"gclid":{"type":["string","null"],"description":"Google Ads click id."},"fbclid":{"type":["string","null"],"description":"Meta click id."}}},"device":{"type":"object","description":"Parsed from the user agent.","required":["type","browser","browser_version","os"],"properties":{"type":{"type":["string","null"],"description":"desktop, mobile, tablet, bot or unknown."},"browser":{"type":["string","null"],"description":"Browser name; in-app browsers (Instagram, LinkedIn) are named as such."},"browser_version":{"type":["string","null"],"description":"Browser version."},"os":{"type":["string","null"],"description":"Operating system."}}},"location":{"type":"object","description":"Where the event was sent from. Every field is null when the row was never located.","required":["country_code","country","region_code","region","city","timezone","isp","org","asn","is_mobile_network","is_proxy","is_hosting","source"],"properties":{"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 country code, e.g. IN."},"country":{"type":["string","null"],"description":"Country name, e.g. India."},"region_code":{"type":["string","null"],"description":"The lookup provider's region code, e.g. MH."},"region":{"type":["string","null"],"description":"Region name, e.g. Maharashtra."},"city":{"type":["string","null"],"description":"City name."},"timezone":{"type":["string","null"],"description":"IANA time zone, e.g. Asia/Kolkata."},"isp":{"type":["string","null"],"description":"Internet provider, from the IP lookup."},"org":{"type":["string","null"],"description":"Organisation owning the address, from the IP lookup."},"asn":{"type":["integer","null"],"description":"Autonomous system number, from the IP lookup."},"is_mobile_network":{"type":["boolean","null"],"description":"The connection is a mobile carrier (not the same as the device being a phone). null unless source is ip-api."},"is_proxy":{"type":["boolean","null"],"description":"The address is a known proxy or VPN. null unless source is ip-api."},"is_hosting":{"type":["boolean","null"],"description":"The address belongs to a hosting provider. null unless source is ip-api."},"source":{"type":["string","null"],"description":"How the location was found: ip-api (live lookup), apache-log (backfilled), none (looked up, no answer), or null (never looked up — every row before 15 Sep 2026)."}}},"bot":{"type":"object","description":"Crawler classification from the user agent. Bots are flagged, never dropped.","required":["is_bot","kind"],"properties":{"is_bot":{"type":"boolean","description":"True for a crawler or tool."},"kind":{"type":["string","null"],"description":"search, ai, seo, social, monitor, tool or other."}}},"consent_state":{"type":["string","null"],"description":"Consent at capture: granted, denied, not_asked or exempt."},"is_identified":{"type":"boolean","description":"The browser had been identified (signed in) when this event was sent."},"school":{"type":"object","description":"The school the page is about, when it is about one.","required":["id","slug"],"properties":{"id":{"type":["string","null"],"description":"School id."},"slug":{"type":["string","null"],"description":"School URL slug."}}},"program":{"type":"object","description":"The programme the page is about, when it is about one.","required":["id","slug"],"properties":{"id":{"type":["string","null"],"description":"Programme id."},"slug":{"type":["string","null"],"description":"Programme URL slug."}}},"properties":{"type":"object","additionalProperties":{"type":"string"},"description":"Event-specific properties, all as strings (e.g. section_id, section_label, active_ms on section_viewed; href, target_domain, link_text on outbound_click; form_id, form_name, form_provider on form events; query, count, filters, sort on finder_ events). Keys that could identify a person (matching /email|phone|mobile|whatsapp|^name$|first_?name|last_?name|full_?name|^ip$|address|passport|birth|^dob$|^contact_id$|^submission_id$/i) are removed unless the key has personal data access. `value` is always removed from the scholarship application (form_provider = seed). The course-finder questionnaire (form_provider = seed-quiz) keeps its answers in `value`."},"ip_address":{"type":["string","null"],"description":"The raw IP address the event came from (stored since 15 Sep 2026). Only with personal data access (a server key holding `people`); otherwise the field is absent.","x-personal-data":true},"user_agent":{"type":["string","null"],"description":"The full user agent string. Only with personal data access (a server key holding `people`); otherwise the field is absent.","x-personal-data":true},"contact_id":{"type":["string","null"],"description":"CRM contact id stamped on the event by a form submission. Only with personal data access (a server key holding `people`); otherwise the field is absent.","x-personal-data":true}}}},"pageviews":{"type":"integer","description":"Pageviews in the session."},"entry_path":{"type":["string","null"],"description":"Path of the first event — the landing page."},"site":{"type":["string","null"],"description":"Hostname of the first event."},"utm_source":{"type":["string","null"],"description":"utm_source on the first event."},"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 of the first located event; null when nothing in the session was located."},"device_type":{"type":["string","null"],"description":"Device type of the first event."},"events_truncated":{"type":"boolean","description":"The session had more than 1000 events and only the first 1000 are listed."}}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":{"session_id":"c3d9e1f0-6a2b-4d7c-8e5f-9a0b1c2d3e4f","visitor_id":"5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","raw_visitor_id":"5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","started_at":"2026-09-21T10:18:41.002Z","ended_at":"2026-09-21T10:31:09.870Z","duration_seconds":748.9,"events":[{"id":"0d6f4c1a-7e2b-4a9c-b3d5-8f1e2a3b4c5d","name":"section_viewed","time":"2026-09-21T10:20:03.123Z","visitor_id":"5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","raw_visitor_id":"5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","session_id":"c3d9e1f0-6a2b-4d7c-8e5f-9a0b1c2d3e4f","site":"seedglobaleducation.com","path":"/study-abroad/scholarships","url":"https://seedglobaleducation.com/study-abroad/scholarships?utm_source=SEED309&utm_medium=email","title":"Scholarships — SEED Global Education","page_type":"scholarship_list","referrer":null,"referrer_domain":null,"channel":"email","utm":{"source":"SEED309","medium":"email","campaign":"sept-newsletter","term":null,"content":null},"click_ids":{"gclid":null,"fbclid":null},"device":{"type":"mobile","browser":"Instagram","browser_version":"350.0","os":"iOS"},"location":{"country_code":"IN","country":"India","region_code":"MH","region":"Maharashtra","city":"Pune","timezone":"Asia/Kolkata","isp":"Example Carrier","org":"Example Org","asn":64500,"is_mobile_network":true,"is_proxy":false,"is_hosting":false,"source":"ip-api"},"bot":{"is_bot":false,"kind":null},"consent_state":"granted","is_identified":true,"school":{"id":null,"slug":null},"program":{"id":null,"slug":null},"properties":{"section_id":"faq","section_label":"Frequently asked questions","section_index":"4","active_ms":"12840","visible_ms":"15000","max_ratio":"100"},"ip_address":"203.0.113.7","user_agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) Instagram 350.0","contact_id":"crm-000123"}],"pageviews":5,"entry_path":"/study-abroad/scholarships","site":"seedglobaleducation.com","utm_source":"SEED309","country_code":"IN","device_type":"mobile","events_truncated":false},"meta":{"request_id":"req_01J8ZK3Q7X5W2V9T4R6N8M0P1B","generated_at":"2026-09-22T09:00:00.000Z"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/people":{"get":{"operationId":"listPeople","summary":"List identified people","description":"People who signed in on our sites, most recently (re-)identified first. Requires personal data access: a server key with the people scope (browser keys never). q searches email and name (case-insensitive, contains). updated_since returns records written at or after that time — use it for incremental syncs; a person who signs in again while you page moves to the top and is caught by the next updated_since run. With a site, only people seen on it. Default limit 100, maximum 1000.","tags":["People"],"x-scope":"people","parameters":[{"$ref":"#/components/parameters/Site"},{"name":"q","in":"query","required":false,"description":"Text contained in the email or the name, case-insensitive.","schema":{"type":"string"}},{"name":"updated_since","in":"query","required":false,"description":"Only records written at or after this date (2026-09-01) or UTC time (2026-09-01T10:00:00Z).","schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"One page of people.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","description":"People, most recently identified first.","items":{"type":"object","description":"One identified person. The whole record is personal data.","required":["visitor_id","raw_visitor_id","linked_ids","person_key","contact_id","name","email","phone","first_seen","last_seen","updated_at","properties"],"properties":{"visitor_id":{"type":"string","description":"Canonical visitor id of the person — joins to /v1/visitors and /v1/events."},"raw_visitor_id":{"type":"string","description":"The visitor id the identity record is filed under (the browser they signed in on)."},"linked_ids":{"type":"array","description":"Every visitor id known to belong to this person, ascending.","items":{"type":"string","description":"Raw visitor id."}},"person_key":{"type":["string","null"],"description":"The key the site identified the person by (its CRM contact id). Personal data: only with personal data access, which this endpoint requires.","x-personal-data":true},"contact_id":{"type":["string","null"],"description":"Latest CRM contact id stamped on any of their events. Personal data: only with personal data access, which this endpoint requires.","x-personal-data":true},"name":{"type":["string","null"],"description":"Name sent at sign-in. Personal data: only with personal data access, which this endpoint requires.","x-personal-data":true},"email":{"type":["string","null"],"description":"Email sent at sign-in. Personal data: only with personal data access, which this endpoint requires.","x-personal-data":true},"phone":{"type":["string","null"],"description":"Phone number sent at sign-in. Personal data: only with personal data access, which this endpoint requires.","x-personal-data":true},"first_seen":{"type":["string","null"],"description":"Their first event under any linked id, all time. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"last_seen":{"type":["string","null"],"description":"Their latest event under any linked id, all time. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"updated_at":{"type":"string","description":"When the identity record was last written (their latest sign-in). The order of the list and what updated_since compares. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"properties":{"type":"object","additionalProperties":{"type":"string"},"description":"Everything the site sent at sign-in, as strings — today {source, name, email, phone}. Personal data: only with personal data access, which this endpoint requires.","x-personal-data":true}},"x-personal-data":true}},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":[{"visitor_id":"5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","raw_visitor_id":"b7e14d2c-8a3f-4e5b-9c6d-1f2a3b4c5d6e","linked_ids":["5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","b7e14d2c-8a3f-4e5b-9c6d-1f2a3b4c5d6e"],"person_key":"crm-000123","contact_id":"crm-000123","name":"Ada Lovelace","email":"ada@example.com","phone":"+91 00000 00000","first_seen":"2026-09-02T08:11:20.450Z","last_seen":"2026-09-21T10:31:09.870Z","updated_at":"2026-09-21T10:25:44.010Z","properties":{"source":"finder","name":"Ada Lovelace","email":"ada@example.com","phone":"+91 00000 00000"}}],"meta":{"request_id":"req_01J8ZK3Q7X5W2V9T4R6N8M0P1B","generated_at":"2026-09-22T09:00:00.000Z","query":{"site":null,"q":"ada","updated_since":null},"pagination":{"limit":100,"next_cursor":"eyJ2IjoxLCJ0IjoiMjAyNi0wOS0yMSAxMDoyMDowMy4xMjMiLCJpZCI6Ii4uLiJ9","has_more":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}},"/v1/people/{visitor_id}":{"get":{"operationId":"getPerson","summary":"Get one identified person","description":"One identified person by any of their visitor ids, with every linked id. Requires personal data access. 404 when none of their ids ever signed in.","tags":["People"],"x-scope":"people","parameters":[{"name":"visitor_id","in":"path","required":true,"description":"Any visitor id of the person.","schema":{"type":"string"}},{"name":"site","in":"query","required":false,"description":"Optional hostname. A key restricted to some sites reads only those; without ?site= the record is checked against all of them.","schema":{"type":"string"}}],"responses":{"200":{"description":"The person.","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","description":"One identified person. The whole record is personal data.","required":["visitor_id","raw_visitor_id","linked_ids","person_key","contact_id","name","email","phone","first_seen","last_seen","updated_at","properties"],"properties":{"visitor_id":{"type":"string","description":"Canonical visitor id of the person — joins to /v1/visitors and /v1/events."},"raw_visitor_id":{"type":"string","description":"The visitor id the identity record is filed under (the browser they signed in on)."},"linked_ids":{"type":"array","description":"Every visitor id known to belong to this person, ascending.","items":{"type":"string","description":"Raw visitor id."}},"person_key":{"type":["string","null"],"description":"The key the site identified the person by (its CRM contact id). Personal data: only with personal data access, which this endpoint requires.","x-personal-data":true},"contact_id":{"type":["string","null"],"description":"Latest CRM contact id stamped on any of their events. Personal data: only with personal data access, which this endpoint requires.","x-personal-data":true},"name":{"type":["string","null"],"description":"Name sent at sign-in. Personal data: only with personal data access, which this endpoint requires.","x-personal-data":true},"email":{"type":["string","null"],"description":"Email sent at sign-in. Personal data: only with personal data access, which this endpoint requires.","x-personal-data":true},"phone":{"type":["string","null"],"description":"Phone number sent at sign-in. Personal data: only with personal data access, which this endpoint requires.","x-personal-data":true},"first_seen":{"type":["string","null"],"description":"Their first event under any linked id, all time. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"last_seen":{"type":["string","null"],"description":"Their latest event under any linked id, all time. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"updated_at":{"type":"string","description":"When the identity record was last written (their latest sign-in). The order of the list and what updated_since compares. ISO 8601 UTC, e.g. 2026-09-21T10:20:03.123Z.","format":"date-time"},"properties":{"type":"object","additionalProperties":{"type":"string"},"description":"Everything the site sent at sign-in, as strings — today {source, name, email, phone}. Personal data: only with personal data access, which this endpoint requires.","x-personal-data":true}},"x-personal-data":true},"meta":{"$ref":"#/components/schemas/Meta"}}},"example":{"data":{"visitor_id":"5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","raw_visitor_id":"b7e14d2c-8a3f-4e5b-9c6d-1f2a3b4c5d6e","linked_ids":["5f0c2a8e-3b6d-4c1e-9a7f-2d4b8e6c1a90","b7e14d2c-8a3f-4e5b-9c6d-1f2a3b4c5d6e"],"person_key":"crm-000123","contact_id":"crm-000123","name":"Ada Lovelace","email":"ada@example.com","phone":"+91 00000 00000","first_seen":"2026-09-02T08:11:20.450Z","last_seen":"2026-09-21T10:31:09.870Z","updated_at":"2026-09-21T10:25:44.010Z","properties":{"source":"finder","name":"Ada Lovelace","email":"ada@example.com","phone":"+91 00000 00000"}},"meta":{"request_id":"req_01J8ZK3Q7X5W2V9T4R6N8M0P1B","generated_at":"2026-09-22T09:00:00.000Z"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ServerBusy"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"sak_<key_id>_<secret>","description":"The API key as a bearer token: `Authorization: Bearer sak_…`. Keys are created and cancelled in the dashboard’s \"API access\" section. Never put a key in the URL."},"apiKeyHeader":{"type":"apiKey","in":"header","name":"X-API-Key","description":"The same API key in its own header, for clients that cannot set Authorization."}},"parameters":{"From":{"name":"from","in":"query","required":false,"description":"First day to include, as YYYY-MM-DD. A UTC day, included in the range. Default: 29 days before `to`, so the default range is the 30 days ending today (unless the endpoint says otherwise). `from` must not be after `to`, and the two may be at most 400 days apart.","schema":{"type":"string","format":"date","example":"2026-09-01"}},"To":{"name":"to","in":"query","required":false,"description":"Last day to include, as YYYY-MM-DD. A UTC day, included in the range. Default: today (UTC), which is still being written to, so its figures grow during the day.","schema":{"type":"string","format":"date","example":"2026-09-21"}},"Site":{"name":"site","in":"query","required":false,"description":"One website, by hostname, e.g. `seedglobaleducation.com`. Default: every site the key may read, added together. GET /v1/sites lists the sites. A key limited to one site reads that site by default; a key limited to several must name one (400 invalid_parameter otherwise); naming a site the key may not read answers 403 forbidden_site.","schema":{"type":"string","maxLength":253,"example":"seedglobaleducation.com"}},"Bots":{"name":"bots","in":"query","required":false,"description":"Which traffic to count. `human` (default) leaves out search engines, AI scrapers and other software visitors; `bot` counts only those; `all` counts both. Automated visits are flagged, never deleted.","schema":{"type":"string","enum":["human","bot","all"],"default":"human"}},"Limit":{"name":"limit","in":"query","required":false,"description":"Rows per answer, a whole number of at least 1. The default and the ceiling are set per endpoint and given in its description (lists: 100 by default, at most 1000). A value above the ceiling is lowered to it rather than refused; meta.pagination.limit or meta.query says what was used.","schema":{"type":"integer","minimum":1,"example":100}},"Cursor":{"name":"cursor","in":"query","required":false,"description":"Where the next page starts. Pass back `meta.pagination.next_cursor` from the previous answer, unchanged, with the same other parameters. Opaque: do not build or edit one. Leave it out for the first page.","schema":{"type":"string","maxLength":1000,"pattern":"^[A-Za-z0-9_-]+$"}},"UtmCampaign":{"name":"utm_campaign","in":"query","required":false,"description":"Narrow the figures to one campaign: the `utm_campaign` tag on the link people arrived through, e.g. `open_day_delhi`. Matched exactly as recorded, upper and lower case included — GET /v1/stats/campaigns lists the values that exist, and an empty value is the same as leaving it out. Default: every campaign, and untagged traffic with them. TWO ATTRIBUTION GRAINS, on purpose. On /v1/stats/overview, /timeseries, /pages and /section-pages the filter counts the EVENTS that carried the tag, which is what \"traffic that arrived tagged\" means and what each of those rows claims. On /v1/stats/funnel, /forms, /form-dropoff and /forms/{form_id} it counts every event of the PEOPLE who carried it: anyone who fired at least one tagged event inside the same range, site and bots filter (any-touch, not first-touch). Measuring a sequence per event would manufacture the drop-off it is meant to report, so the cohort form is used there. Two consequences worth knowing before the numbers are compared: the two families do not tie, so a funnel step can exceed the visitor count the overview gives for the same campaign; and cohorts overlap, so two campaigns that touched the same person both count that person and campaigns do not add up to the whole. Taken by GET /v1/stats/overview, /timeseries, /pages, /section-pages, /funnel, /forms, /form-dropoff and /forms/{form_id}. Every other endpoint ignores it and leaves it out of meta.query — GET /v1/stats/sections and GET /v1/stats/section-dropoff in particular cannot offer it, because the rollup they read has no campaign columns at all, so a campaign-shaped answer there could only be an unfiltered one.","schema":{"type":"string","maxLength":200,"example":"open_day_delhi"}},"UtmSource":{"name":"utm_source","in":"query","required":false,"description":"Narrow the figures to one `utm_source` — in SEED’s links a partner or placement code such as `SEED309`, not a readable name, so pass one through rather than showing it to a person. Matched exactly as recorded; GET /v1/stats/campaigns lists the values that exist. Default: every source, and untagged traffic with them. Given together with `utm_campaign`, one single event had to carry both tags. TWO ATTRIBUTION GRAINS, on purpose. On /v1/stats/overview, /timeseries, /pages and /section-pages the filter counts the EVENTS that carried the tag, which is what \"traffic that arrived tagged\" means and what each of those rows claims. On /v1/stats/funnel, /forms, /form-dropoff and /forms/{form_id} it counts every event of the PEOPLE who carried it: anyone who fired at least one tagged event inside the same range, site and bots filter (any-touch, not first-touch). Measuring a sequence per event would manufacture the drop-off it is meant to report, so the cohort form is used there. Two consequences worth knowing before the numbers are compared: the two families do not tie, so a funnel step can exceed the visitor count the overview gives for the same campaign; and cohorts overlap, so two campaigns that touched the same person both count that person and campaigns do not add up to the whole. Taken by GET /v1/stats/overview, /timeseries, /pages, /section-pages, /funnel, /forms, /form-dropoff and /forms/{form_id}. Every other endpoint ignores it and leaves it out of meta.query — GET /v1/stats/sections and GET /v1/stats/section-dropoff in particular cannot offer it, because the rollup they read has no campaign columns at all, so a campaign-shaped answer there could only be an unfiltered one.","schema":{"type":"string","maxLength":200,"example":"SEED309"}}},"schemas":{"Pagination":{"type":"object","description":"Where this page sits in a longer list.","required":["limit","next_cursor","has_more"],"properties":{"limit":{"type":"integer","description":"The page size actually used."},"next_cursor":{"type":["string","null"],"description":"Pass back as ?cursor= for the next page; null on the last page."},"has_more":{"type":"boolean","description":"True while there is another page to fetch."}}},"Meta":{"type":"object","description":"About the answer rather than part of it. Present on every response, success or error.","required":["request_id","generated_at"],"properties":{"request_id":{"type":"string","description":"The id of this request, also sent as the X-Request-Id header. Quote it when reporting a problem."},"generated_at":{"type":"string","format":"date-time","description":"When the answer was produced, ISO 8601 UTC."},"query":{"type":"object","additionalProperties":true,"description":"The filters actually applied, defaults included (from, to, site, bots and any endpoint filters). An echo of what was used, not of the raw query string."},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"ErrorCode":{"type":"string","description":"A stable machine word to branch on. The message beside it may be reworded; the code will not.","enum":["unauthorized","key_revoked","key_in_url","forbidden_scope","forbidden_site","origin_not_allowed","invalid_parameter","not_found","rate_limited","server_busy","internal_error"],"x-enum-descriptions":[{"code":"unauthorized","status":401,"meaning":"No API key was sent, or the key is not one we issued.","action":"Send the key in the Authorization or X-API-Key header. Check it was copied whole."},{"code":"key_revoked","status":401,"meaning":"The key was cancelled in the dashboard.","action":"Ask for a new key. A cancelled key never works again."},{"code":"key_in_url","status":400,"meaning":"A key was sent in the address (query string). Addresses end up in logs and browser history.","action":"Move the key into a header, and treat that key as leaked: cancel it and create a new one."},{"code":"forbidden_scope","status":403,"meaning":"The key does not hold the permission this endpoint needs. details.required_scope names it.","action":"Use a key with that permission, or create one in the dashboard."},{"code":"forbidden_site","status":403,"meaning":"The key is limited to certain sites and the site you asked for is not one of them.","action":"Ask for a site the key may read (GET /v1/sites lists them), or use a key without the limit."},{"code":"origin_not_allowed","status":403,"meaning":"A browser called from a web address the key was not issued for, or a server key was used from a web page.","action":"Call from a server, or use a browser key created for that address."},{"code":"invalid_parameter","status":400,"meaning":"A parameter is missing, malformed or out of range. error.param names it.","action":"Fix that parameter. The message says what is expected."},{"code":"not_found","status":404,"meaning":"There is no such endpoint, or no such visitor, session or person.","action":"Check the path against this reference, and the id you asked for."},{"code":"rate_limited","status":429,"meaning":"The key made more requests this minute than it is allowed, or too many bad keys came from one address.","action":"Wait the number of seconds in the Retry-After header, then carry on."},{"code":"server_busy","status":503,"meaning":"The API or its database is busy, or cannot check keys for a moment.","action":"Wait the number of seconds in Retry-After and try again. It clears in seconds."},{"code":"internal_error","status":500,"meaning":"Something went wrong on our side.","action":"Try again later. If it persists, report it with the request_id."}]},"Error":{"type":"object","description":"Every failure has this shape, whatever the endpoint.","required":["error","meta"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"$ref":"#/components/schemas/ErrorCode"},"message":{"type":"string","description":"A sentence for a person. Never contains SQL or internal detail; may be reworded."},"param":{"type":"string","description":"The parameter at fault, when there is one (invalid_parameter, forbidden_site)."},"details":{"type":"object","additionalProperties":true,"description":"Extra facts for some codes, e.g. `required_scope` on forbidden_scope."}}},"meta":{"type":"object","required":["request_id","generated_at"],"properties":{"request_id":{"type":"string","description":"The id of this request. Quote it when reporting a problem."},"generated_at":{"type":"string","format":"date-time","description":"When the answer was produced, ISO 8601 UTC."}}}}}},"responses":{"BadRequest":{"description":"A parameter is wrong (invalid_parameter, naming it in error.param), or a key was sent in the URL (key_in_url).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_parameter":{"summary":"A malformed date","value":{"error":{"code":"invalid_parameter","message":"from must be a date like 2026-09-01.","param":"from"},"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z"}}},"key_in_url":{"summary":"A key in the query string","value":{"error":{"code":"key_in_url","message":"Never put an API key in a URL: URLs are kept in server logs, proxies and browser history. Send it as \"Authorization: Bearer <key>\" or \"X-API-Key: <key>\". If a real key was sent, revoke it and make a new one."},"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z"}}}}}}},"Unauthorized":{"description":"No key, an unknown key (unauthorized), or a cancelled one (key_revoked).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"unauthorized":{"summary":"No key or an unknown key","value":{"error":{"code":"unauthorized","message":"This API key is not recognised."},"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z"}}},"key_revoked":{"summary":"A cancelled key","value":{"error":{"code":"key_revoked","message":"This API key has been revoked. Ask for a new one."},"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z"}}}}}}},"Forbidden":{"description":"The key may not read this: a missing permission (forbidden_scope), a site it is not limited to (forbidden_site), or a browser calling from an address the key was not issued for (origin_not_allowed).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"forbidden_scope":{"summary":"A missing permission","value":{"error":{"code":"forbidden_scope","message":"This key cannot read this. It needs the \"stats\" permission.","details":{"required_scope":"stats"}},"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z"}}},"forbidden_site":{"summary":"A site outside the key’s limit","value":{"error":{"code":"forbidden_site","message":"This key cannot read finder.seedglobaleducation.com.","param":"site"},"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z"}}},"origin_not_allowed":{"summary":"A browser on another website","value":{"error":{"code":"origin_not_allowed","message":"This key is not issued for this web origin."},"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z"}}}}}}},"NotFound":{"description":"No such endpoint, or no such visitor, session or person.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"not_found":{"summary":"Nothing there","value":{"error":{"code":"not_found","message":"There is no visitor with that id."},"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z"}}}}}}},"RateLimited":{"description":"The key used up its requests for this clock minute, or this address sent 20 bad keys in a minute. Wait Retry-After seconds.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"rate_limited":{"summary":"Too many requests","value":{"error":{"code":"rate_limited","message":"This key may make 120 requests a minute. Try again in 17 seconds.","details":{"limit":120,"reset_at":"2026-09-21T10:21:00.000Z"}},"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z"}}}}}}},"ServerBusy":{"description":"The analytics database is busy. Nothing is wrong with the request: wait Retry-After seconds and send it again.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"server_busy":{"summary":"Busy","value":{"error":{"code":"server_busy","message":"The analytics database is busy. Try again in a few seconds."},"meta":{"request_id":"req_01J8ZK3T5V9QW4N7","generated_at":"2026-09-21T10:20:03.123Z"}}}}}}}},"headers":{"XRequestId":{"description":"The id of this request, the same as meta.request_id. Quote it when you report a problem.","schema":{"type":"string","example":"req_01J8ZK3T5V9QW4N7"}},"XRateLimitLimit":{"description":"Requests this key may make per clock minute. On every answer to a request with a valid key.","schema":{"type":"integer","example":120}},"XRateLimitRemaining":{"description":"Requests left in the current minute.","schema":{"type":"integer","example":0}},"XRateLimitReset":{"description":"When the allowance fills up again: the end of the current clock minute, as a Unix time in seconds.","schema":{"type":"integer","example":1790072460}},"RetryAfter":{"description":"Seconds to wait before trying again.","schema":{"type":"integer","example":5}}}}}