The Oberon Debugger: From Workspace to API

Read time:

7–11 minutes

Every analyst who has stared at Analysis Workspace knows the feeling. You build the perfect freeform table. The breakdowns are elegant. The segments actually isolate the behaviour you care about. Then someone asks, “Can this number appear in our BI dashboard and refresh every fifteen minutes?” Or, “Can we trigger a Slack alert the moment conversion rate drops below target today?” Or, “Can our personalisation engine read this morning’s top-performing campaign and act on it now?”

These require live data via API. Scheduled reports are too slow. Data Warehouse and Data Feeds are excellent for bulk historical export, but they do not serve queries that must run and return while the day is still unfolding.

The obstacle is usually the API. Adobe Analytics Reporting API 2.0 is powerful, but its JSON payloads are finicky. Misplace one identifier, and you spend an hour debugging a 400 error. The Oberon debugger removes that friction. It exposes the exact API requests that Analysis Workspace sends on your behalf, turning a polished visual report into reusable code in minutes. This post explains how to enable it, how to read the payloads it reveals, and how to turn one working Workspace report into a reliable programmatic integration.

Why the API Matters for Working Analysts

Analysis Workspace is unmatched for exploration, but it is not always the right place for recurring or integrated insight. Scheduled PDFs and CSVs are fine for human inboxes, yet they break the moment you need to combine Adobe data with a CRM, a BI tool, a data warehouse, or an operational alert. Data teams want trusted Adobe metrics in a pipeline. Product managers want blended dashboards. Analysts want thresholds that trigger notifications rather than morning report rituals.

Reporting API 2.0 is the same engine that powers Workspace, exposed as a clean JSON interface. That parity is the key. If a report works visually, the equivalent API request is already validated. You do not have to reverse-engineer the platform. You just have to capture its own language.

Enabling the Oberon Debugger

The debugger is hidden in plain sight inside Adobe Analytics.

Adobe Analytics Workspace Help menu with the Enable debugger option selected
  1. Open any project in Analysis Workspace.
  2. Click Help in the top navigation.
  3. Select Enable debugger.
  4. Confirm the modal that appears.

A small bug icon now appears in the top-right corner of every visualisation that fetches data. Click it, and you will see the actual API requests Workspace made to render that table or chart. Do not expect a single call. A freeform table with one or more breakdowns often triggers several coordinated requests: one for the parent dimension, then additional calls for each expanded child dimension. Even a single table can spawn a small fleet of requests. Treat the first, top-level request as your starting template, then inspect the breakdown calls only when you need to reproduce nested drill-downs programmatically.

The Oberon debugger menu showing a list of captured API requests for a Freeform Table

The freeform table request is usually the most useful starting point because it carries the full dimension, metric, segment, and date-range definition.

This is not a toy for curiosity. It is the fastest way to learn the JSON shape of a real production report without touching documentation.

Screenshot of the Oberon debugger showing the XML and JSON request and response payloads for a freeform table in Adobe Analytics

What the Payload Actually Looks Like

Every Reporting API 2.0 request is a POST to:

POST https://analytics.adobe.io/api/{globalCompanyId}/reports

The body contains five core pieces. If you study one request from the Oberon debugger, each piece maps cleanly to something you already understand from the Workspace interface.

rsid

The report suite ID. This is the data container you selected. Every request must target exactly one suite.

globalFilters

This is where the report-wide constraints live. The most common is the date range, written as an ISO interval. If you applied a segment to the panel or the project, it also appears here as a second filter object. Seeing this in the debugger is the easiest way to learn how segment IDs are referenced.

metricContainer

The metrics you dragged into the table. Each entry has an identifier such as metrics/pageviews or metrics/visits. If you used a calculated metric, the debugger reveals its full internal ID rather than the friendly name. This removes the guesswork when you want to reuse that metric elsewhere.

dimension

The dimension you broke the table down by. The API uses identifiers prefixed with variables/, such as variables/page or variables/evar7. This is more reliable than trying to map friendly labels through documentation.

settings

Pagination and row limits. The limit controls how many rows come back in one call. The page is zero-based offset. For high-cardinality reports you will page through results, but for a first proof of concept a single page is enough.

Here is a simplified example that fetches page views and visits by page for a single month.

{
    "rsid": "your-report-suite-id",
    "globalFilters": [
        {
            "type": "dateRange",
            "dateRange": "2024-01-01T00:00:00Z/2024-01-31T23:59:59Z"
        }
    ],
    "metricContainer": {
        "metrics": [{ "id": "metrics/pageviews" }, { "id": "metrics/visits" }]
    },
    "dimension": "variables/page",
    "settings": {
        "limit": 100,
        "page": 0
    }
}

The Oberon debugger hands you a request that already works. Your job is to copy the shape, swap the dynamic values, and make it repeatable.

Reading the Response

The response is not a flat list. It is a grid with metadata, pagination, and rows. Understanding that grid prevents a common beginner mistake: assuming the first metric in your request is always the first value in every data array. It is, but the response is designed for multiple metrics and breakdowns, so it carries a columns object that maps metric IDs to positions.

A typical response contains:

  • Pagination blocktotalPagesnumbertotalElements, and pageSize. These tell you whether to loop for more rows.
  • Columns definition: the dimension ID and a list of columnIds that map to your requested metrics.
  • Rows: each row has an itemId, the human-readable value, and a data array with metric values in request order.
  • Summary data: pre-aggregated totals, filtered totals, and column maxima and minima.
{
    "totalPages": 877,
    "firstPage": true,
    "lastPage": false,
    "number": 0,
    "totalElements": 8768,
    "columns": {
        "dimension": {
            "id": "variables/page",
            "type": "string"
        },
        "columnIds": ["0", "1", "2"]
    },
    "rows": [
        {
            "itemId": "3306266643",
            "value": "home",
            "data": [219567, 151478, 151478]
        },
        {
            "itemId": "2796092754",
            "value": "category 5",
            "data": [90943, 71248, 71248]
        }
    ],
    "summaryData": {
        "filteredTotals": [3080619, 357996, 357996],
        "totals": [3080619, 424407, 424407]
    }
}

The summaryData block is especially useful when you are validating that your API request matches the Workspace view. If the totals differ, your filter or segment is not quite the same yet. Fix the payload until they align, then you know your code is faithful.

From Debugger to Production Script

Here is the workflow I recommend once you have captured a payload.

  1. Reproduce the report in Workspace first. Get the numbers right visually. Add the segments, calculated metrics, and breakdowns exactly as you want them. This is your source of truth.
  2. Enable the debugger and capture the request. Paste the JSON into a scratch file and clean it up. Remove any fields that look like transient request metadata if you plan to generalise the call.
  3. Replace fixed values with parameters. Turn the absolute date range into a relative one or accept it as an argument. Make the report suite ID configurable. If you later want to run this across multiple suites, parameterisation now saves hours.
  4. Write a thin wrapper. Use the language your team already works in. Python with requests, Node.js with axios, or even a curl prototype. The first goal is to make the same call and see identical numbers to two decimal places.
  5. Handle pagination. Most real reports span more than one page. Loop using the page parameter until lastPage is true, or until your counter reaches totalPages. For very large datasets consider whether Reporting API 2.0 is the right tool; the Data Warehouse and Data Feeds exist for bulk export.
  6. Cache responsibly. The API returns the same numbers as Workspace, so it is tempting to call it continuously. Cache results for the duration of your reporting cadence and respect rate limits. Adobe throttles aggressive callers.
  7. Validate against the UI one last time. Run your script for a known date range and compare every total back to Workspace. Discrepancies almost always mean a missing segment, a mismatched date range, or a different report suite.

Common Traps

The Oberon debugger removes most of the mystery, but a few pitfalls remain.

Believing the UI and API always return identical row counts. They do at the total level, but Workspace may apply client-side sorting, top-or-bottom filters, or row limits that are not part of the API request. If your script returns more rows, check whether Workspace is hiding infrequent line items.

Ignoring package entitlements. Some features, such as contribution analysis or certain breakdowns, are gated by your Adobe Analytics package. If the API rejects a request that works in Workspace, verify that the same user context and package apply.

Forgetting about time zones. Workspace displays data in the report suite time zone. Your API request does not automatically know your local zone. If you schedule a daily report, fetch yesterday relative to the suite’s configured time zone, not your laptop clock.

Hardcoding segments and calculated metrics. Segment IDs and calculated metric IDs can change if someone recreates or duplicates them. Store identifiers in configuration and version control them alongside your code.

When to Use Reporting API 2.0

This API is a surgical instrument, not a data lake pump. Use it when you need precise, filtered, on-demand data. Executive dashboards, custom alerting, automated email reports, and BI tool integrations are ideal. When you need millions of raw hit rows or historical reconstruction, reach for Data Warehouse or Data Feeds instead.

The Oberon debugger is what makes the API approachable. Without it, Reporting API 2.0 is a wall of documentation and cryptic identifiers. With it, every report you can build in Workspace becomes a working API template. That turns analysts into builders and dashboards into durable infrastructure.

Where to Go Deeper

Book cover for Adobe Analytics: A Champion's Handbook by Leo Lau, covering concept, theory, troubleshooting, best practice, and case study

This post covers the practical bridge between Workspace and code, but Reporting API 2.0 has far more to offer. Segmentation, date comparisons, breakdown paging, calculated metrics, and error-handling patterns all deserve their own treatment. I cover the full anatomy of the API, plus the Oberon debugger, response parsing, Python and Node.js examples, and integration strategy in Chapter 7.2 of Adobe Analytics: A Champion’s Handbook.

If your team is moving from ad-hoc reporting to programmatic analytics, that chapter gives you the patterns to build integrations that scale from thousands of rows to billions without losing your sanity.