Skip to content

Periods

One frozen calendar month or quarter with every metric, its prior value, delta and direction, plus the metric registry that defines each figure.

Code example

Request
curl -X GET 'https://api.trakkr.ai/get-period-summary?brand_id=00000000-0000-4000-8000-81f286d10c3c&period=2026-08&view=summary&compare=true&months=12' \
  -H "Authorization: Bearer $TRAKKR_API_KEY"
Response · 200 OK
{
  "brand": {},
  "period": {
    "key": "Synthetic sample",
    "kind": "Synthetic sample",
    "label": "Synthetic sample",
    "start": "Synthetic sample",
    "end": "Synthetic sample",
    "status": "Synthetic sample",
    "source": "Synthetic sample",
    "restatements": [],
    "coverage": {},
    "fields_computed": [],
    "fields_missing": [],
    "notes": []
  },
  "metrics": {},
  "breakdowns": {},
  "headline_metric_ids": [],
  "groups": [],
  "metric_meta": {}
}

Synthetic example. Values are made up.

API key required

60 req/min

Why periods

The dashboard headline is a single day's report, and a days window recomputes over a rolling window that answers differently on the 3rd and the 9th. That drift is what puts an inverted arrow in a month-over-month deck. A period is a scoping parameter, not a date filter: period=2026-08 names the row frozen when August closed, and it answers identically however later it is asked.

A closed month is frozen on the 1st and read from the archive. The open month is computed month to date and says so (status: open). A quarter is derived from its three months by a rule per metric: averages weighted by measured days or runs, counts summed, end-of-period figures taken from the last archived month. A recompute that changes a stored figure is recorded as a restatement rather than silently overwriting it. The same resolver serves the API, the MCP server, the Agent and the Reports page, so a number cannot differ between them for the same period.

Endpoint

GET/get-period-summary

Authenticate with Authorization: Bearer $TRAKKR_API_KEY. Key and access guide

Request parameters

brand_idstring | nullqueryOptional

Brand UUID. Required unless brand_ids is given; never both.

Format: uuid

brand_idsstring[] | nullqueryOptional

Several brands at once: brand UUIDs, comma-separated or repeated, up to 12 after de-duplication, instead of brand_id. Returns one compact row per brand per closed month with the prior month's delta already computed; view, compare and include do not apply. period as YYYY-MM keeps that month and the month before it; quarters are not available for a brand list yet. months caps how many closed months are returned (at most 12). Ids that are not among your brands are listed in excluded and never read.

periodstring | nullqueryOptional

A month as YYYY-MM or a quarter as YYYY-Qn. Defaults to the most recently closed month. With brand_ids, a month keeps that month and the month before it; quarters are not available for a brand list yet.

viewstringqueryOptional

summary (default), or list: the index of archived months and quarters

Default: "summary" · Options: "summary", "list"

comparebooleanqueryOptional

Include the prior period and the computed deltas

Default: true

includestring | nullqueryOptional

Comma-separated extras. 'definitions' adds each metric's one-line definition.

monthsintegerqueryOptional

view=list: how many closed months to index. With brand_ids: how many closed months to return per brand, at most 12.

Default: 12 · Minimum: 1 · Maximum: 36

Responses and errors
200Successful Response

application/json

PeriodSummaryResponse

brandobjectRequired

periodobjectRequired

What a period-scoped response actually resolved.

Fields in period

keystringRequired

kindstringRequired

labelstringRequired

startstringRequired

endstringRequired

statusstringRequired

sourcestringRequired

frozen_atstring | nullOptional

pipeline_versionstring | nullOptional

restated_atstring | nullOptional

restatementsobject[]Optional

Default: []

Fields in restatements

Array of object. Default: []

object. Additional keys are allowed.

coverageobjectOptional

Default: {}

fields_computedstring[]Optional

Default: []

Fields in fields_computed

Array of string. Default: []

string.

fields_missingstring[]Optional

Default: []

Fields in fields_missing

Array of string. Default: []

string.

notesstring[]Optional

Default: []

Fields in notes

Array of string. Default: []

string.

monthsobject | nullOptional

rank_sourcestring | nullOptional

priorobject | nullOptional

Fields in prior
PeriodMeta

keystringRequired

kindstringRequired

labelstringRequired

startstringRequired

endstringRequired

statusstringRequired

sourcestringRequired

frozen_atstring | nullOptional

pipeline_versionstring | nullOptional

restated_atstring | nullOptional

restatementsobject[]Optional

Default: []

Fields in restatements

Array of object. Default: []

object. Additional keys are allowed.

coverageobjectOptional

Default: {}

fields_computedstring[]Optional

Default: []

Fields in fields_computed

Array of string. Default: []

string.

fields_missingstring[]Optional

Default: []

Fields in fields_missing

Array of string. Default: []

string.

notesstring[]Optional

Default: []

Fields in notes

Array of string. Default: []

string.

monthsobject | nullOptional

rank_sourcestring | nullOptional

null

null.

metricsobjectRequired

breakdownsobjectOptional

Default: {}

headline_metric_idsstring[]Optional

Default: []

Fields in headline_metric_ids

Array of string. Default: []

string.

groupsobject[]Optional

Default: []

Fields in groups

Array of object. Default: []

object. Additional keys are allowed.

metric_metaobjectOptional

Default: {}

definitionsobject | nullOptional

PeriodIndexResponse

brandobjectRequired

periodsobject[]Required

Fields in periods

Array of object.

keystringRequired

kindstringRequired

labelstringRequired

statusstringRequired

sourcestringRequired

startstring | nullOptional

endstring | nullOptional

data_statusstring | nullOptional

frozen_atstring | nullOptional

restated_atstring | nullOptional

complete_report_setboolean | nullOptional

months_archivedinteger | nullOptional

days_elapsedinteger | nullOptional

quartersobject[]Optional

Default: []

Fields in quarters

Array of object. Default: []

keystringRequired

kindstringRequired

labelstringRequired

statusstringRequired

sourcestringRequired

startstring | nullOptional

endstring | nullOptional

data_statusstring | nullOptional

frozen_atstring | nullOptional

restated_atstring | nullOptional

complete_report_setboolean | nullOptional

months_archivedinteger | nullOptional

days_elapsedinteger | nullOptional

currentobjectRequired

Fields in current

keystringRequired

kindstringRequired

labelstringRequired

statusstringRequired

sourcestringRequired

startstring | nullOptional

endstring | nullOptional

data_statusstring | nullOptional

frozen_atstring | nullOptional

restated_atstring | nullOptional

complete_report_setboolean | nullOptional

months_archivedinteger | nullOptional

days_elapsedinteger | nullOptional

PeriodPortfolioResponse

monthsobject[]Required

Fields in months

Array of object.

keystringRequired

labelstringRequired

startstringRequired

endstringRequired

brandsobject[]Required

Fields in brands

Array of object.

idstringRequired

namestring | nullOptional

websitestring | nullOptional

domainstring | nullOptional

notesstring[]Optional

Default: []

Fields in notes

Array of string. Default: []

string.

rowsobject[]Required

Fields in rows

Array of object.

brand_idstringRequired

periodstringRequired

labelstringRequired

startstringRequired

endstringRequired

statusstringRequired

sourcestringRequired

data_statusstring | nullOptional

frozen_atstring | nullOptional

restatedbooleanOptional

Default: false

report_daysinteger | nullOptional

metricsobjectOptional

Default: {}

notestring | nullOptional

metric_idsstring[]Required

Fields in metric_ids

Array of string.

string.

metric_metaobjectOptional

Default: {}

currentobjectRequired

notesstring[]Optional

Default: []

Fields in notes

Array of string. Default: []

string.

excludedobject[]Optional

Default: []

Fields in excluded

Array of object. Default: []

brand_idstringRequired

reasonstringRequired

401Missing, malformed, or expired credentials

application/json

detailstring | object | nullOptional

errorstring | nullOptional

402The current plan does not fund this operation

application/json

detailstring | object | nullOptional

errorstring | nullOptional

403Invalid credentials, missing brand access, or insufficient role

application/json

detailstring | object | nullOptional

errorstring | nullOptional

422Validation Error

application/json

detailobject[]Optional

Fields in detail

Array of object.

locstring | integer[]Required

Fields in loc

Array of string | integer.

string

string.

integer

integer.

msgstringRequired

typestringRequired

429Rate limit exceeded

application/json

detailstring | object | nullOptional

errorstring | nullOptional

500The operation failed

application/json

detailstring | object | nullOptional

errorstring | nullOptional

503Authentication, entitlement, or a required dependency is temporarily unavailable

application/json

detailstring | object | nullOptional

errorstring | nullOptional

OpenAPI source

Returns the whole month or quarter: every single-number metric under metrics with the prior period alongside and the delta and direction already computed, the lists and maps under breakdowns, and the unit and direction of each metric under metric_meta.

This endpoint is rate limited to 60 requests per minute per API key. See the Rate Limits page for handling 429 responses.
Try GET /get-period-summary

view=summary (default)

Without period the summary is for the most recently closed month. The period block says exactly what was resolved; read status and source before publishing a figure.

Request
curl -X GET 'https://api.trakkr.ai/get-period-summary?brand_id=00000000-0000-4000-8000-81f286d10c3c&period=2026-08&view=summary&compare=true&months=12' \
  -H "Authorization: Bearer $TRAKKR_API_KEY"
Response · 200 OK
{
  "brand": {},
  "period": {
    "key": "Synthetic sample",
    "kind": "Synthetic sample",
    "label": "Synthetic sample",
    "start": "Synthetic sample",
    "end": "Synthetic sample",
    "status": "Synthetic sample",
    "source": "Synthetic sample",
    "restatements": [],
    "coverage": {},
    "fields_computed": [],
    "fields_missing": [],
    "notes": []
  },
  "metrics": {},
  "breakdowns": {},
  "headline_metric_ids": [],
  "groups": [],
  "metric_meta": {}
}

Synthetic example. Values are made up.

Direction is decided server-side from the metric's own point of view. Rank 11 to 10 is a negative delta, a positions_gained of 1 and a direction of up. Print the direction word, not the sign of the delta.

Breakdowns

Lists and maps live under breakdowns, each with the prior period alongside where it exists.

  • model_visibility: models[] with visibility, presence, measured days and mentions per model, plus strongest, weakest and zero_models
  • top_competitors: competitors[] with rank, visibility, prior_rank, positions_gained, visibility_delta and new_in_list, plus notable_change, the rival that gained most
  • top_prompts: the prompts with the highest average visibility, each flagged new_entrant against the prior period
  • tag_visibility: average visibility per prompt tag with zero_prompts and the prior value
  • perception_categories: categories keyed by category with score, prior and direction, plus strongest and weakest
  • perception_competitors: average perception score per tracked competitor, the brand included
  • descriptors_end: primary, emerging and fading descriptors from the last perception run of the period
  • citation_top_pages: the pages naming the brand that were cited most, with citations inside the period and the models that cited them
  • citation_top_gap_domains: the domains cited most with no page naming the brand, the outreach targets

view=list

The archive index: which closed months exist for the brand, the quarters they form, and the open month. Use it before asking for a period so a missing month is not mistaken for a month with no data.

Request
curl -X GET 'https://api.trakkr.ai/get-period-summary?brand_id=00000000-0000-4000-8000-81f286d10c3c&view=list&compare=true&months=12' \
  -H "Authorization: Bearer $TRAKKR_API_KEY"
Response · 200 OK
{
  "brand": { "id": "00000000-0000-4000-8000-81f286d10c3c", "name": "Notion", "website": "https://notion.so" },
  "periods": [
    {
      "key": "2026-08",
      "kind": "month",
      "label": "August 2026",
      "start": "2026-08-01",
      "end": "2026-08-31",
      "status": "closed",
      "source": "archive",
      "data_status": "complete",
      "frozen_at": "2026-09-01T03:12:44+00:00",
      "restated_at": null,
      "complete_report_set": true
    },
    {
      "key": "2026-07",
      "kind": "month",
      "label": "July 2026",
      "start": "2026-07-01",
      "end": "2026-07-31",
      "status": "closed",
      "source": "archive",
      "data_status": "complete",
      "frozen_at": "2026-08-01T03:10:02+00:00",
      "restated_at": "2026-08-14T09:30:11+00:00",
      "complete_report_set": true
    }
  ],
  "quarters": [
    { "key": "2026-Q3", "kind": "quarter", "label": "Q3 2026", "start": "2026-07-01", "end": "2026-09-30", "status": "open", "source": "derived_from_months", "months_archived": 2 }
  ],
  "current": { "key": "2026-09", "kind": "month", "label": "September 2026", "status": "open", "source": "computed", "days_elapsed": 11 }
}

Synthetic example. Values are made up.

Status, sources and restatements

status is closed or open. An open month is month to date, is never persisted, carries no month-end rank, and will change until it closes. A quarter with a month still running is open too.

source says where the figures came from. archive is the frozen row. computed is the open month, or a closed month that was not archived yet and has just been computed from retained raw data and stored; it is frozen from then on, and one request fills at most one month. derived_from_months is a quarter. missing means the archive holds nothing for that brand and month and the fill was not possible in this request; every metric is null and notes says so.

A recompute that changes a stored figure appends an entry to restatements with at, note, the pipeline version before and after, and changed keyed by field with the old and new value. The original frozen_at is kept and restated_at marks the latest restatement, so a report can name the change instead of showing a different number with no explanation.

Perception and competitor metrics are withheld on plans without those features. The metric comes back with value: null, its breakdown is dropped, and period.notes names the withheld groups.

Get Metrics

GET/get-metrics

Authenticate with Authorization: Bearer $TRAKKR_API_KEY. Key and access guide

Responses and errors
200Successful Response

application/json

groupsobject[]Required

Fields in groups

Array of object.

object. Additional keys are allowed.

metricsobjectRequired

comparison_kindsstring[]Required

Fields in comparison_kinds

Array of string.

string.

401Missing, malformed, or expired credentials

application/json

detailstring | object | nullOptional

errorstring | nullOptional

402The current plan does not fund this operation

application/json

detailstring | object | nullOptional

errorstring | nullOptional

403Invalid credentials, missing brand access, or insufficient role

application/json

detailstring | object | nullOptional

errorstring | nullOptional

429Rate limit exceeded

application/json

detailstring | object | nullOptional

errorstring | nullOptional

500The operation failed

application/json

detailstring | object | nullOptional

errorstring | nullOptional

503Authentication, entitlement, or a required dependency is temporarily unavailable

application/json

detailstring | object | nullOptional

errorstring | nullOptional

OpenAPI source

The metric registry: every figure the period endpoints report, with its label, one-line definition, unit, direction of improvement, how a month is formed from daily readings, and how two periods compare. It takes no brand_id. Product tooltips, the Learn metrics page and the MCP trakkr://metrics resource render from the same source.

Request
curl -X GET 'https://api.trakkr.ai/get-metrics' \
  -H "Authorization: Bearer $TRAKKR_API_KEY"
Response · 200 OK
{
  "groups": [
    {
      "id": "visibility",
      "label": "Visibility",
      "tagline": "How often and how prominently the brand shows up in AI answers.",
      "metrics": [
        {
          "id": "visibility_avg",
          "label": "Visibility average",
          "group": "visibility",
          "unit": "score",
          "precision": 1,
          "better": "higher",
          "aggregation": "mean_daily",
          "comparison": "points",
          "kind": "measure",
          "definition": "How prominently AI models mention the brand across every tracked prompt and model, weighted by where it appears in the answer, averaged over each measured day in the period. 0 to 100.",
          "aggregation_note": "Average of the daily values inside the period, one value per day.",
          "quarter_rule": "weighted_days",
          "learn_url": "https://trakkr.ai/learn/metrics#visibility"
        }
      ]
    }
  ],
  "metrics": {
    "visibility_avg": { "...": "the same entry, keyed by id" }
  },
  "comparison_kinds": ["points", "percent", "positions", "none"]
}

Synthetic example. Values are made up.

The 35 metric ids, in the order a report reads them. Visibility: visibility_avg, presence_avg, mentions_total, position_avg (answer position when mentioned, not competitor rank), visibility_min, visibility_max, report_days, model_visibility. Competitors: rank_end, rank_avg, rank_pool_end, top_competitors. Citations: citations_total, citation_brand_mentions, citation_brand_pages_cumulative_end, citation_days, citation_source_domains_end, citation_source_domains_brand_end, citation_source_domain_share_pct, citation_top_pages, citation_top_gap_domains. Prompts: prompts_measured, prompts_with_visibility, prompt_coverage_pct, top_prompts, tag_visibility. Perception: perception_score_avg, perception_categories, perception_competitors, descriptors_end, perception_runs. Site health: audit_score_end, audit_open_issues_end, audit_count. Traffic: ai_sessions_total, AI-referred sessions from the connected analytics property, read once, three days after the month ends, so the provider has finished counting it.

The definitions in prose are on the Learn metrics page.

period on the other endpoints

Seven read endpoints accept period=YYYY-MM or period=YYYY-Qn and then read their own shape from the archive. When period is set, days is ignored and the response carries the same period block as above. A malformed key returns 400.

  • /get-scores: every view. Not combinable with tag_ids or prompt_id (400); visibility by tag for the period is in the summary's breakdowns.
  • /get-rankings: view=overall only. win_rate and threat_count are null, and a month with no archived rank returns 404.
  • /get-models: total_queries is the number of measured days for the model, presence is filled, and the average_position and top-3 fields are null.
  • /get-competitor-data: view=summary only, and the response takes a period shape: your_rank, rank_pool, your_visibility, competitors[] with prior_rank, positions_gained, visibility_delta and new_in_list, notable_change and perception_competitors.
  • /get-citations: view=top_pages and view=analytics. appearance_count is the page's citations inside the period, with appearance_count_period and models alongside. In analytics, top_domains are the domains cited most with no page naming the brand, and period_figures carries the brand-page figures.
  • /get-perception: view=dashboard and view=metrics. perception_score.change_period is the change against the prior period.
  • /get-audits: the audit whose score stood at the end of the period. Site health for the period is audit_score_end in the summary.

Use Cases

  • Build a monthly client report that fetches the same figures again next quarter
  • Compare August with July, or Q3 with Q2, with the direction already right for ranks
  • Check status, source and restatements before a number goes into a deck
  • Render metric labels, units and definitions from /get-metrics instead of hard-coding them
  • List what is archived with view=list before backfilling a warehouse