Skip to main content
POST /functions/v1/export-user-analytics
Returns a single JSON document with report-style analytics for every domain on your account — both domains you own and domains shared with you. Unlike the dashboard charts and PDF report, which group smaller crawlers into “Other” and “Other social”, this endpoint breaks traffic out into each individual bot.
Always call this endpoint from a server-side environment (backend API, serverless function, build script, etc.). Never include your API key in client-side code — it will be visible to anyone inspecting your frontend.
Programmatic (API key) access requires the Pro plan and above — requests from Starter accounts return 403 plan_upgrade_required. The Export all (JSON) button in the Analytics dashboard is available on all plans.

Request

Headers

HeaderRequiredDescription
AuthorizationYesBearer hado_sk_your_key_here
Content-TypeYesapplication/json

Body Parameters

ParameterTypeRequiredDescription
periodstringNoReporting window: 1d, 7d, 30d, 90d, or 365d. Defaults to 30d. Applies to every domain in the response.
The export always covers every domain your account can access — there is no per-domain parameter.

Example Request

curl -X POST https://api.hadoseo.com/functions/v1/export-user-analytics \
  -H "Authorization: Bearer hado_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "period": "30d"
  }'

Response

Success (200)

{
  "generatedAt": "2026-06-29T12:00:00.000Z",
  "period": "30d",
  "userId": "00000000-0000-0000-0000-000000000000",
  "domainCount": 1,
  "domains": [
    {
      "domain": "example.com",
      "domainId": "11111111-1111-1111-1111-111111111111",
      "role": "owner",
      "summary": {
        "totalCrawls": 1840,
        "prerenders": 412,
        "cachedViews": 1520,
        "cacheMisses": 320,
        "cacheHitRate": 82.6
      },
      "botTotals": {
        "googlebot": 920,
        "googleextendedbot": 14,
        "bingbot": 210,
        "openaibot": 88,
        "anthropicbot": 31,
        "perplexitybot": 12,
        "twitterbot": 40,
        "facebookbot": 35,
        "linkedinbot": 22,
        "slackbot": 9,
        "discordbot": 4,
        "whatsappbot": 6,
        "telegrambot": 3,
        "pinterestbot": 2,
        "snapchatbot": 0,
        "redditbot": 5,
        "metabot": 7,
        "quorabot": 1,
        "social_other": 8,
        "applebot": 18,
        "amazonbot": 11,
        "baidubot": 6,
        "yandexbot": 9,
        "duckduckbot": 4,
        "bytespiderbot": 25
      },
      "botSeries": [
        { "date": "2026-06-28", "googlebot": 41, "bingbot": 9, "openaibot": 3, "bytespiderbot": 1 }
      ],
      "topPages": [
        {
          "url": "https://example.com/blog/launch",
          "seoScore": 92,
          "seoIssuesCount": 1,
          "botTotal": 134
        }
      ],
      "seo": {
        "good": 120,
        "needsWork": 18,
        "poor": 4,
        "unknown": 9,
        "totalPages": 151,
        "totalIssues": 47
      }
    }
  ]
}
Each botSeries entry contains a count for every bot listed in botTotals. The example above is trimmed to a few bots for brevity; the actual response includes all of them, with 0 where there was no traffic.

Fields

FieldTypeDescription
generatedAtstringISO 8601 timestamp of when the export was produced.
periodstringThe period applied: 1d, 7d, 30d, 90d, or 365d.
userIdstringThe account that owns the API key.
domainCountnumberNumber of domains included.
domains[].domainstringThe domain name.
domains[].domainIdstringThe domain’s unique ID.
domains[].rolestringAccess level for this domain: owner, manager, or viewer.
domains[].summaryobjectPeriod totals: totalCrawls, prerenders, cachedViews, cacheMisses, cacheHitRate.
domains[].botTotalsobjectTotal visits per individual bot for the period.
domains[].botSeriesarrayPer-day breakdown; each entry has a date plus a count for every bot.
domains[].topPagesarrayTop pages by bot traffic: url, seoScore, seoIssuesCount, botTotal.
domains[].seoobjectSEO health bucket counts (good, needsWork, poor, unknown) plus totalPages and totalIssues.

Granular bot breakdown

Every bot is reported as its own field. The bots that the dashboard and PDF report fold into “Other” and “Other social” each appear individually here:
Bucket in reportsIndividual bots in botTotals / botSeries
Other socialslackbot, discordbot, whatsappbot, telegrambot, pinterestbot, snapchatbot, redditbot, metabot, quorabot, social_other
Otherapplebot, amazonbot, baidubot, yandexbot, duckduckbot, bytespiderbot
The named bots already shown in reports are also present individually: googlebot, googleextendedbot, bingbot, openaibot, anthropicbot, perplexitybot, twitterbot, facebookbot, and linkedinbot.
social_other is a catch-all for social crawlers that can’t be identified individually. It’s reported as its own field rather than merged into another bot.

Error Responses

StatusBodyDescription
400{ "error": "invalid_request" }Invalid period value
401{ "error": "invalid_api_key" }API key is missing, invalid, or revoked
403{ "error": "plan_upgrade_required" }Programmatic export requires the Pro plan or above
429{ "error": "rate_limit_exceeded", "usage": 300, "limit": 300 }Monthly or per-minute rate limit exceeded
When you receive a 429, the usage and limit fields tell you where you stand against your monthly quota. Per-minute limits (60 req/min) reset automatically after 60 seconds. See Authentication for plan limits.

Examples

JavaScript / Node.js

const response = await fetch(
  "https://api.hadoseo.com/functions/v1/export-user-analytics",
  {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.HADOSEO_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ period: "30d" }),
  },
);

const report = await response.json();
for (const domain of report.domains) {
  console.log(domain.domain, domain.botTotals);
}
Prefer a one-off download? The Analytics dashboard has an Export all (JSON) button that produces the same document for the selected period without needing an API key — and it’s available on every plan.