Skip to main content
Glama

Analytics Legends — SAP Analytics Intelligence

Public SAP AI & analytics day-rate aggregate

get_day_rate_benchmark
Read-onlyIdempotent

The PUBLIC day-rate aggregate for SAP AI & analytics freelance work: min/max daily rate by country, specialisation and seniority — daily_rate_min / daily_rate_max (plus daily_rate_median, daily_rate_p10, daily_rate_p90 when the source publishes them), every amount in the row's own currency — with source, source date, confidence and the sample the source states. This is the free aggregate published at analyticslegends.ai/api/market-rates.json, and it is SMALL — a few dozen rows at most, every one of them a secondary source (a published market study or a job-board scan), and sample_size is null on most of them. NO COUNT IS WRITTEN HERE ON PURPOSE: _meta.tranche_total_row_count and the rows themselves are the live measure. A frozen pair stood here until 2026-08-27 — '11 rows on 2026-08-09 … sample_size null on 8 of them' — and the second half was WRONG (7 of 11) while the first was still right, which is the whole argument against writing either. NOTHING IS HELD BACK BEHIND IT: there is no paid counterpart to this aggregate. The community-contribution path exists (public.rate_contributions) but publishes nothing yet — v_community_rate_aggregates and v_rate_index are still empty, because a contributed rate only surfaces once a cell holds enough submissions to be reported without identifying anyone. So whatever percentile a source row happens to carry is served here, free, to everyone. The GB row carries a median, p10 and p90, and its own note says its min/max ARE the 25th and 75th percentiles. What is missing from this answer is missing from THIS aggregate; it is not a paid tier. THIS IS NOT THE ONLY RATE THE PLATFORM PUBLISHES, AND ON THE QUESTIONS THIS MARKET ASKS MOST IT IS THE THINNER ONE. The website carries a rate_band per live radar posting for signed-in subscribers — a panel-inferred P25–P75 band per (seniority × product × region) cell, Eursap n=312 plus the Analytics Legends operator panel. This server does not serve it (find_opportunities.rate_band is null on every row, with or without a key). The grid covers EUROPEAN cells only — DACH, FR/Benelux, UK/IE, Southern EU, Eastern EU, Nordics — and there it prices exactly the cells this small aggregate cannot (Senior Datasphere DACH, Senior BDC DACH), where specialisation:"bdc" here returns nothing. When this tool comes back empty for a country × product: in one of those European regions, say the AGGREGATE holds no row and that subscribers read the platform's band on the posting pages; ANYWHERE ELSE (Americas, APAC, Africa, Middle East) say the platform publishes no rate for that cell at any tier — never that subscribers get one. The two are different instruments: this one is a published market study, that one is an editorial benchmark attached to a live posting. Read _meta.available_countries / available_specialisations / available_seniorities — they are computed from the aggregate on every call — before concluding that a rate is unpublished, and quote each row with its own currency, its confidence and its source date.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
countryNoISO-3166-1 alpha-2 country code, e.g. DE, FR, CH.
seniorityNoe.g. senior, principal.
specialisationNoOne of the codes the aggregate actually holds — analytics_all, bw, bw4hana, bw4hana_sac, sac, datasphere (2026-08-09; the live list comes back as `_meta.available_specialisations` on every call). They are NOT evenly spread across countries: DE holds analytics_all only, at three seniorities, and datasphere exists for FR alone, as a median with confidence 'low'. There is no bdc row and no joule row in THIS aggregate — but the platform does price BDC: `find_opportunities` carries a panel-inferred band on the live postings, €1,000–€1,400/day P25–P75 for Senior BDC on 52 German postings (2026-08-10). A code this aggregate does not hold returns 0 rows and the available codes; it never widens to a neighbouring band, and 0 here does not mean the platform is silent.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
rowsYes
toolYes
_metaNo
_attributionYes
result_countYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedOutput schema / properties / rows / items / properties / indicative / description
      Previous value: -"true = orientation only: the source is a proxy (non-SAP BI band, generic ERP, agency monthly contract or marketing average). Never quote it as the SAP analytics rate of its country."New value: +"true = orientation only: the source is a proxy (non-SAP BI band, generic ERP, agency monthly contract or marketing average). Never quote it as the SAP AI & analytics rate of its country."
  2. Changed21 schema fields changed
    • addedOutput schema / properties / rows / items / properties / accessed
      Added value: +{
      +  "description": "date the source was read (YYYY-MM-DD)",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / conversion
      Added value: +{
      +  "description": "how an hourly or monthly source figure was turned into a day rate",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_max_aud
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_max + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_max_hkd
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_max + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_max_jpy
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_max + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_max_nzd
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_max + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_max_sgd
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_max + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_median_aud
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_median + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_median_hkd
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_median + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_median_jpy
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_median + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_median_nzd
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_median + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_median_sgd
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_median + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_min_aud
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_min + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_min_hkd
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_min + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_min_jpy
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_min + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_min_nzd
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_min + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_min_sgd
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_min + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / indicative
      Added value: +{
      +  "description": "true = orientation only: the source is a proxy (non-SAP BI band, generic ERP, agency monthly contract or marketing average). Never quote it as the SAP analytics rate of its country.",
      +  "type": [
      +    "boolean",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / sap_scope
      Added value: +{
      +  "description": "what the source actually measures: sap_analytics | sap_general | erp_general | bi_non_sap",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / source_period
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / source_type
      Added value: +{
      +  "description": "primary_agency_guide | primary_job_ads | aggregator | marketing",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
  3. Changed26 schema fields changed
    • addedOutput schema / properties / rows / items / properties / basis
      Added value: +{
      +  "description": "external_published_median | external_published_range | panel — see /api/market-rates.json _meta.basis_values.",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / confidence
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / currency / description
      Added value: +"ISO-4217 unit of every daily_rate_* amount on THIS row (EUR, GBP, CHF) — never an envelope constant."
    • addedOutput schema / properties / rows / items / properties / daily_rate_max
      Added value: +{
      +  "description": "Upper bound of the published band, in `currency`.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_max_chf
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_max + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_max_eur
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_max + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_max_gbp
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_max + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_median
      Added value: +{
      +  "description": "Median when the source publishes one, in `currency`.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_median_eur
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_median + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_median_gbp
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_median + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_min
      Added value: +{
      +  "description": "Lower bound of the published band, in `currency`.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_min_chf
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_min + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_min_eur
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_min + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_min_gbp
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_min + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_p10
      Added value: +{
      +  "description": "10th percentile when the source publishes one, in `currency`.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_p10_gbp
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_p10 + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_p90
      Added value: +{
      +  "description": "90th percentile when the source publishes one, in `currency`.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / daily_rate_p90_gbp
      Added value: +{
      +  "description": "DEPRECATED — read daily_rate_p90 + currency.",
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / note
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / sample_basis
      Added value: +{
      +  "description": "What `sample_size` counts (profiles, vacancies…), when the source says.",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / sample_size / description
      Added value: +"The sample the SOURCE states behind this row; null when it states none — never estimated."
    • addedOutput schema / properties / rows / items / properties / source
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / source_date
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / source_url
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / trend
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / rows / items / properties / yoy_change_pct
      Added value: +{
      +  "type": [
      +    "number",
      +    "null"
      +  ]
      +}
  4. Changed1 schema field changed
    • changedInput schema / properties / specialisation / description
      Previous value: -"One of the codes the aggregate actually holds — analytics_all, bw, bw4hana, bw4hana_sac, sac, datasphere (2026-08-09; the live list comes back as `_meta.available_specialisations` on every call). They are NOT evenly spread across countries: DE holds analytics_all only, at three seniorities, and datasphere exists for FR alone, as a median with confidence 'low'. There is no bdc row and no joule row anywhere in the aggregate — the two products this market asks about most are the two it cannot price. A code the aggregate does not hold returns 0 rows and the available codes; it never widens to a neighbouring band."New value: +"One of the codes the aggregate actually holds — analytics_all, bw, bw4hana, bw4hana_sac, sac, datasphere (2026-08-09; the live list comes back as `_meta.available_specialisations` on every call). They are NOT evenly spread across countries: DE holds analytics_all only, at three seniorities, and datasphere exists for FR alone, as a median with confidence 'low'. There is no bdc row and no joule row in THIS aggregate — but the platform does price BDC: `find_opportunities` carries a panel-inferred band on the live postings, €1,000–€1,400/day P25–P75 for Senior BDC on 52 German postings (2026-08-10). A code this aggregate does not hold returns 0 rows and the available codes; it never widens to a neighbouring band, and 0 here does not mean the platform is silent."
  5. Changed1 schema field changed
    • changedInput schema / properties / specialisation / description
      Previous value: -"e.g. datasphere, bdc, sac, bw4hana, joule."New value: +"One of the codes the aggregate actually holds — analytics_all, bw, bw4hana, bw4hana_sac, sac, datasphere (2026-08-09; the live list comes back as `_meta.available_specialisations` on every call). They are NOT evenly spread across countries: DE holds analytics_all only, at three seniorities, and datasphere exists for FR alone, as a median with confidence 'low'. There is no bdc row and no joule row anywhere in the aggregate — the two products this market asks about most are the two it cannot price. A code the aggregate does not hold returns 0 rows and the available codes; it never widens to a neighbouring band."
  6. Changed6 schema fields changed
    • removedOutput schema / properties / rows / items / properties / citation_note
      Removed value: -{
      -  "type": "string"
      -}
    • changedOutput schema / properties / rows / items / properties / country / type
      Previous value: -"string"New value: +[
      +  "string",
      +  "null"
      +]
    • changedOutput schema / properties / rows / items / properties / currency / type
      Previous value: -"string"New value: +[
      +  "string",
      +  "null"
      +]
    • changedOutput schema / properties / rows / items / properties / sample_size / type
      Previous value: -"integer"New value: +[
      +  "integer",
      +  "null"
      +]
    • changedOutput schema / properties / rows / items / properties / seniority / type
      Previous value: -"string"New value: +[
      +  "string",
      +  "null"
      +]
    • changedOutput schema / properties / rows / items / properties / specialisation / type
      Previous value: -"string"New value: +[
      +  "string",
      +  "null"
      +]
  7. Changed3 schema fields changed
    • addedOutput schema / properties / rows / items / properties / citation_note
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / rows / items / properties / citation_scope
      Added value: +{
      +  "enum": [
      +    "record",
      +    "section_hub"
      +  ],
      +  "type": "string"
      +}
    • addedOutput schema / properties / rows / items / properties / citation_url
      Added value: +{
      +  "type": "string"
      +}
  8. Changed1 schema field changed
    • addedOutput schema / properties / rows / items / properties / currency
      Added value: +{
      +  "type": "string"
      +}
  9. First observed

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/idempotent/destructive=false, so safety is covered. The description adds real behavioral context beyond that: the aggregate is small and secondary-source only, sample_size is null on most rows, and no paid tier withholds data. The 'frozen pair' digression and the argument about deliberately omitting counts are self-indulgent rather than informative, but they do not contradict the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The first sentence is front-loaded and useful, but the body sprawls across many paragraphs of internal editorializing: a frozen statistic debunked at length, meta-commentary about why counts are not written, and repeated restatements of the same aggregate-vs-panel distinction. A large fraction of the text does not help an agent call the tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need not be explained, and the description instead covers the genuinely tricky parts: cross-tier boundaries, empty-cell semantics, currency-per-row, and _meta fields to consult. It is arguably over-complete on tangential matters but nothing an agent needs to interpret results correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema already carries detailed semantics per parameter (country code format, seniority examples, the full specialisation code list and its caveats). The description adds mainly the empty-result interpretation, which is usage guidance rather than parameter meaning. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence names a specific verb+resource+scope: the public day-rate aggregate with min/max daily rate by country, specialisation and seniority, including exact field names. It also explicitly distinguishes itself from the sibling find_opportunities (which carries rate_band). However, the signal is buried under several paragraphs of editorial argument, so an agent must work to extract the core purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Strong conditional guidance: it tells the agent what to report when the tool returns empty (a European cell → say the AGGREGATE holds no row; elsewhere → say no rate is published at any tier), and names find_opportunities.rate_band as the alternative instrument. It stops short of a crisp 'use this when X vs Y' rule and repeats the same distinction multiple times.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.