Skip to content

Climate Risk and Emissions by Emmi

Emmi employs a top-down approach to calculate company emissions, transition risk, physical climate risk, and asset hazard analysis across five asset classes. The analysis runs entirely within your Snowflake account, without data ever leaving your environment. It can be run through a guided user interface, or directly via Snowflake SQL so it can be incorporated into production-grade data pipelines.

Installation

Climate Risk and Emissions by Emmi is available as a Snowflake listing. Installing it takes a couple of minutes and happens entirely in Snowsight.

Before you start. You need the ACCOUNTADMIN role, or a role with the IMPORT SHARE and CREATE DATABASE privileges.

  1. Sign in to Snowsight, then select Catalog and Apps from the navigation menu.
  2. Locate Climate Risk and Emissions by Emmi (it may appear under Recently shared with you, or you can search for it by name) and select its tile.
  3. Select the Security tab to review the privileges the app requests.
  4. Select Get.
  5. Enter a name for the app and choose the warehouse to install it with.
  6. Select Get again, then choose Open to launch the app or Done to finish.

When you first open the app, Snowsight prompts you to grant the privileges it requests, including CREATE COMPUTE POOL and BIND SERVICE ENDPOINT (which let the app create the compute pool and service that host its user interface) and CREATE WAREHOUSE (a small warehouse the interface uses to run queries). Grant each when prompted. After granting, the interface may take 1-2 minutes to appear the first time you open it while the compute pool starts up; later visits load much faster.

Once installed, open the app and follow the steps in Using the App.

Trial listing

If you installed the app from the limited trial listing, the trial lasts 30 days from installation and the app applies two limits:

  • Each run can process at most 25 input records. A record is one holdings row for Emissions and Climate Risk, or one asset for Geospatial Risk.
  • Across the whole trial, your completed runs can process at most 100 input records in total. Runs that fail or are cancelled do not count towards this total.

The web UI shows how much of the allowance you have used and checks both limits before a run is submitted. A run that exceeds a limit fails straight away with an error naming the limit, whether it was submitted from the web UI or via SQL. The limits do not apply once you move to the full listing; to do so, contact Emmi using the Contact us link in the app.

Asset classes

The app analyses five asset classes. The class a holding is run under decides what its identifier means, which columns are required, and how its numbers are produced. Class names are matched case-sensitively.

  • Public Equity: identifier is an ISIN. Also requires year. Looked up from Emmi's pre-computed company universe.
  • Fixed Income: identifier is an ISIN. Also requires year. Looked up from Emmi's pre-computed company universe.
  • Property: identifier is the asset name. Also requires year and country. Calculated in your account from the property inputs.
  • Infrastructure: identifier is the asset name. Also requires year, country, industry, and industry_classification_system. Calculated in your account from the infrastructure inputs.
  • Private Equity: identifier is the company name. Also requires year, industry, industry_classification_system, and country. Estimated in your account by Emmi's emissions models.

Financial values must already be in US dollars (USD) for every asset class. They are not currency-converted for you, so a portfolio submitted in local currency will produce USD-labelled numbers that are not comparable.

Choosing the asset class

In the interface, the asset class is chosen in the Mapping step: either one class for the whole portfolio, or a column in your data that names the class for each row.

On the SQL path those are the asset_class and asset_class_column params. asset_class and asset_class_column are mutually exclusive: pass one or the other, never both.

  • asset_class: one class for the entire run, e.g. 'Public Equity'.
  • asset_class_column: the name of a column in your input whose value names the class row by row, for a mixed portfolio. Every value in that column must be one of the five names above; unknown, blank or missing values fail the run before anything is computed, and the error lists every distinct offending value at once.

If you pass neither, the default is Private Equity: the whole portfolio is run as private equity, exactly as every run submitted before this release was, so existing pipelines need no change.

Reported emissions

By default the app uses its own estimate for a company even when a reported figure exists for the requested year, so a portfolio is measured on one consistent basis.

The optional prefer_reported param (default off, mirroring the interface's toggle) relaxes that for the looked-up classes, Public Equity and Fixed Income: when the requested year's record is entirely estimated, the previous year's record is used instead if it carries at least one reported scope. It has no effect on Property, Infrastructure or Private Equity, which are computed in your account rather than looked up.

Emissions

Emmi uses the reported data of public companies to train machine learning models to calculate emissions.

Input

To calculate emissions, the app requires a view of your portfolio companies and their financials, one row per company per year. All financial values must be in US dollars (USD); they are not currency-converted for you.

Required:

  • identifier (text): unique company identifier (one row per company per year).
  • year (integer): fiscal year of the financials.
  • industry (text): industry value in your chosen classification system.
  • industry_classification_system (text): the classification system the industry value belongs to. One of factset, gics_l4, rbics_l3, rbics_l4, or anzsic.
  • country (text): country of operation, e.g. United States. Case-insensitive; common aliases like US/UK are accepted.

At least one of these is required for every row (USD):

  • revenue: total revenue.
  • total_assets: total assets.

Recommended (USD); providing these improves the accuracy and data-quality score of the estimate:

  • gppe: gross property, plant and equipment.
  • evic: enterprise value including cash.
  • market_cap: market capitalisation.
  • cap_ex: capital expenditure.

Optional:

  • name (text): a readable company name, carried through to the results.
  • scope1, scope2, scope3 (tCO2e): reported emissions for each scope, used directly when provided.
  • ebitda (USD): earnings before interest, tax, depreciation and amortisation.
  • enterprise_value (USD): enterprise value.
  • employees (count): number of employees.
  • total_debt (USD): total debt.
  • net_debt (USD): net debt.

Note: if you use the interface, your columns can be selected directly and do not need to match the names above. A single industry_classification_system can also be chosen once and applied to the whole view.

Per-class requirements. The tiers above describe the company contract in full, which is what Private Equity uses. The other classes require less of it: Public Equity and Fixed Income need only identifier (an ISIN) and year, because everything else is looked up. See Asset classes for the per-class list, or read required_by_class from SRC.GET_INPUT_CONTRACT().

Two further column groups are available to every class and are optional throughout:

  • Holdings context, carried through to the results untouched: manager_name, fund_name, asset_weight, ownership, security_name, entity_id, security_id.
  • Property and infrastructure inputs, used by those two classes: state, net_lettable_area, building_type, energy_rating, energy_rating_system, market_value, book_value, net_operating_income, operating_cash_flow, gearing_ratio, asset_life_remaining, discount_rate. The monetary ones (market_value, book_value, net_operating_income, operating_cash_flow) are USD, like every other financial value.

Output

For each company and year, the app returns estimated Scope 1, 2, and 3 emissions, combined totals, and a set of carbon-intensity metrics. Reported emissions you supply are used directly and labelled as such.

  • identifier (text): company identifier from your input.
  • name (text): company name from your input, if provided.
  • year (integer): fiscal year.
  • scope1, scope2, scope3 (tCO2e): estimated (or reported) emissions for each scope.
  • scope12 (tCO2e): Scope 1 and 2 combined.
  • scope123 (tCO2e): Scope 1, 2, and 3 combined.
  • scope1_model_name, scope2_model_name, scope3_model_name (text): the model used to produce each scope's estimate.
  • scope1_pcaf, scope2_pcaf, scope3_pcaf (integer, 1 to 5): PCAF data-quality score for each scope (1 is the highest quality).
  • scope1_emission_reporting_status, scope2_emission_reporting_status, scope3_emission_reporting_status (text): whether each scope was reported or estimated.
  • waci_s1, waci_s12, waci_s123 (tCO2e per USD revenue): weighted average carbon intensity at each scope grouping.
  • evic_carbon_intensity_s12, evic_carbon_intensity_s123 (tCO2e per USD EVIC): carbon intensity relative to enterprise value including cash.
  • emissions_used (text): which emissions basis fed the derived metrics.

The results also include the financial fields carried through from your input (such as revenue, total_assets, evic, and market_cap), so the output is self-contained.

Multi-asset-class columns

DATA.EMISSIONS additionally carries the asset-class discriminator, the row key, and the per-holding attributes:

  • ASSET_CLASS (text): the class this row was run under, one of the five display names.
  • INPUT_ROW (integer): the 0-based position of the holding in your input, in submission order.
  • DATA_YEAR (integer): the year of the record actually used, which can differ from YEAR. Empty when nothing resolved.
  • MANAGER_NAME, FUND_NAME, SECURITY_NAME, ASSET_WEIGHT, OWNERSHIP: holdings context carried through from your input.
  • FISCAL_END_DATE, COUNTRY, FACTSET_INDUSTRY: resolved entity attributes.
  • DEBT_TYPE (text): instrument type, for Fixed Income holdings.
  • BUILDING_TYPE (text): building type, for Property assets.

YEAR is always populated and holds the year you requested. DATA_YEAR holds the year of the record actually used: for a looked-up holding they differ whenever the requested year had no record, or prefer_reported selected the prior year. The interface's Year column shows DATA_YEAR.

Results accumulate across runs and are read back filtered by TASK_ID. Because results are holdings-grain (the same identifier can legitimately appear more than once in one portfolio, under different funds or managers), the documented key is (TASK_ID, INPUT_ROW, YEAR) rather than one built on the identifier.

Rows written by earlier versions of the app predate ASSET_CLASS and INPUT_ROW, so those columns are empty for them. They are read back (and downloaded) as Private Equity via a COALESCE at the read boundary, which is what they were. Nothing is rewritten; no backfill runs on upgrade.

Climate Risk

Emmi combines a company's emissions with its financials to measure the value at risk from the low-carbon transition and from the physical effects of climate change, across a range of forward-looking scenarios and analysis years.

Input

Climate risk uses the same company view as the emissions analysis, together with the emissions estimates the app produces. You can run emissions first, or let the app run it for you as part of the climate risk job.

No new columns are needed, but the requirements tighten: each company-year must also provide all of the following, in USD, for its risk metrics to be calculated.

  • total_assets (USD): used as the enterprise value in the risk calculation.
  • ebitda (USD): earnings before interest, tax, depreciation and amortisation.
  • net_debt (USD): net debt.

Climate risk is not a separate task type. It is requested by adding 'risk' to the run's outputs list on the emissions task (alongside 'emissions', or on its own). A risk run always writes both DATA.EMISSIONS and DATA.CLIMATE_RISK, tied together by the run's TASK_ID.

You also choose two run options:

  • Scenarios: one or more climate pathways from the 14 supported scenario ids, drawn from the IPCC, IPCC AR6, NGFS, and IPR scenario families, ranging from orderly net-zero transitions to high-warming pathways:
  • ipcc_net_zero
  • ipcc_two_degree
  • ipcc_four_degree
  • ngfs_below_two_degree
  • ngfs_current_policies
  • ngfs_delayed_transition
  • ngfs_fragmented_world
  • ngfs_net_zero
  • ngfs_low_demand
  • ngfs_ndc
  • ipr_fps
  • ipcc_ar6_sustainable_dev
  • ipcc_ar6_gradual
  • ipcc_ar6_bau
  • Analysis years: the future years to assess. On the engineer path this is the risk_years param, which defaults to [2030, 2035, 2040, 2045, 2050].

Output

Results are written to DATA.CLIMATE_RISK, keyed by (TASK_ID, INPUT_ROW, YEAR, RISK_YEAR, TRANSITION_RISK_SCENARIO): holdings-grain, for the same reason DATA.EMISSIONS is. The table also carries ASSET_CLASS and INPUT_ROW, matching the emissions rows from the same run; the per-holding attribute columns (DEBT_TYPE, BUILDING_TYPE, and the rest) live on DATA.EMISSIONS only. Rows written before this release read back as Private Equity, exactly as for emissions.

For each company, scenario, and analysis year, the app returns the transition and physical value at risk, their combined total, and the budget metrics that show how the company tracks against the scenario's pathway.

  • identifier (text): identifier from your input, the same value as identifier in DATA.EMISSIONS.
  • year (integer): fiscal year of the financials.
  • risk_year (integer): future year the metrics are assessed for.
  • transition_risk_scenario (text): climate scenario the metrics are calculated under.
  • transition_risk (USD): transition value at risk, the cost of the company's emissions under the scenario's carbon price.
  • total_physical_risk (USD): physical value at risk, expected losses from acute and chronic climate impacts.
  • baseline_physical_risk (USD): present-day physical value at risk, for comparison.
  • total_climate_risk (USD): transition and physical value at risk combined.
  • budget (tCO2e): the company's share of the scenario's remaining carbon budget.
  • reduction (tCO2e): emissions reduction implied by the scenario pathway.
  • overspend (tCO2e): emissions in excess of the scenario's carbon budget.
  • temp_alignment (°C): temperature alignment, the warming outcome implied if the wider economy emitted at the company's rate.
  • emissions_used (text): which emissions basis fed the risk metrics.

Geospatial Risk

Emmi assesses the exposure of your physical assets to climate hazards by their location and estimates expected damages from each asset's value. Upload a file of assets in the app's Geospatial Risk section and the app returns physical risk metrics for every asset. Your asset data never leaves your Snowflake account; the hazard maps ship with the app as shared data content.

Pilot coverage: riverine flooding under the rcp4p5 scenario at analysis year 2050. The remaining acute hazards (coastal flooding, tropical cyclone, wildfire), scenarios, and years (2030/2080) follow as data updates without an app upgrade.

Input

In the interface: a CSV or Excel file (first worksheet only), one row per asset. A downloadable template is available in the Geospatial Risk section. Column headers are matched case-insensitively and can be remapped in the UI before validation.

From SQL: a view of your assets with the same columns, bound to the app's input_assets reference (see Via SQL). Column names are matched case-insensitively; Owner Identifier and Name may be left out of the view.

  • Identifier (text, required): unique asset identifier (one row per asset; duplicates are rejected).
  • Longitude (degrees, required): between -180 and 180.
  • Latitude (degrees, required): between -90 and 90.
  • Asset Value (number, required): value of the asset (>= 0), used to calculate expected damages. Use one consistent currency per file.
  • Owner Identifier (text, optional): identifier linking the asset to its owning entity; carried through to outputs for your own owner-level analysis.
  • Name (text, optional): a readable name for the asset.

The file is validated before any run starts; every problem is reported with the affected column and row numbers. On the SQL path a view missing a required column fails the run with an error naming the column.

Output

Results are written to DATA.GEOSPATIAL_RESULTS (one row per asset, hazard, scenario, and year) and can be viewed and downloaded as CSV in the app.

  • owner_identifier, identifier, name (text): carried through from your input unchanged.
  • latitude, longitude (degrees): the queried coordinates.
  • hazard (text): the hazard assessed (riverine_floods in the pilot).
  • scenario (text): the climate scenario the metrics are calculated under (rcp4p5).
  • year (integer): future year the metrics are assessed for (2050).
  • data_available (boolean): false when no hazard data exists at the location (e.g. open ocean); the metric fields are then empty rather than the asset being dropped.
  • aal (share of asset value): average annual loss, the expected yearly loss from the hazard.
  • probability (number): probability of the hazard occurring.
  • intensity (number): intensity of the hazard.
  • depth_meters (metres): expected flood depth (flood hazards; empty otherwise).
  • wind_speed_mps (m/s): maximum sustained wind speed (cyclones; empty otherwise).
  • fire_danger_days (days): number of high fire danger days (wildfire; empty otherwise).
  • asset_value (your currency): as submitted.
  • expected_damages (your currency): aal * asset_value.
  • map_version (text): version of the Emmi hazard maps used (e.g. v1.3).

Using the App

Via the user interface

Open the app in Snowsight and work through the steps in the left sidebar.

  1. Input. Upload a CSV or Excel file of your portfolio holdings (first worksheet only). The parsed rows are previewed here, and you can replace the file at any time. The interface works from the uploaded file; binding a view to the input_portfolio reference is only needed for the SQL path (see Via SQL and the Engineer path). Geospatial Risk has its own upload in the Geospatial Risk section.
  2. Mapping. Choose the asset class (one class for the whole portfolio, or the column that names it per row; see Asset classes), then match your columns to the fields that class needs (columns whose names already match are selected for you) and choose which industry classification system your industry values use. A downloadable CSV template lists every column the app understands but leaves the looked-up and real-asset columns blank in its example rows: the examples are private-equity shaped companies, and show the file format rather than acting as a per-class sample. Then click Check input: this checks every row and reports any problems (missing required fields, non-numeric financials, unrecognised industries, or coordinates outside the valid range). The check must pass before you can run.
  3. Run. Choose the analysis you want and click run. Each analysis runs entirely in your account and can take a few minutes for a large portfolio.
  4. Emissions estimates Scope 1, 2, and 3 for every company.
  5. Climate Risk uses your emissions estimates and financials to measure risk. Selecting it adds 'risk' to the run's outputs (it is not a separate task type), so the run writes both DATA.EMISSIONS and DATA.CLIMATE_RISK. Choose one or more of the supported climate scenarios from the scenario picker.
  6. Geospatial Risk measures physical hazard exposure for assets you upload as a file in the Geospatial Risk section (see above); results land in DATA.GEOSPATIAL_RESULTS.
  7. Results. Review headline figures and a per-entity breakdown for the analysis you ran, and download the full results as CSV. A mixed-class run adds a filter so each class can be reviewed on its own, and Download CSV returns one combined file covering every class: a column a row's own class does not produce is left empty for that row. The combined file is a superset of the equivalent Emmi portfolio-processing export; it keeps the per-analysis-year …PhysicalRisk and …TotalClimateRisk columns that the export drops.
  8. Exclusions. If a run could not use every row (an ISIN that resolves to nothing or to more than one company, for instance), the app records why. The reasons are stored on the run in DATA.TASKS.EXCLUSIONS and offered as a separate Download exclusions button (exclusions.csv), which appears only for runs that actually excluded something. The file has one row per identifier and stage, with repeated fields and reasons merged into a single cell. It, too, is a superset of the portfolio-processing equivalent: the app also records identifiers that could not be resolved at all, which that export does not.

Via SQL

You can also run the app without the UI:

-- grant permissions to the app
GRANT EXECUTE TASK ON ACCOUNT TO APPLICATION <app>;
GRANT EXECUTE MANAGED TASK ON ACCOUNT TO APPLICATION <app>;

-- bind your portfolio view to the app's input_portfolio reference (the UI
-- does not need this; it works from an uploaded file):
CALL <app>.SRC.UPDATE_REFERENCE(
  'input_portfolio', 'ADD',
  SYSTEM$REFERENCE('VIEW', '<your_db>.<your_schema>.<portfolio_view>', 'PERSISTENT', 'SELECT')
);

-- for geospatial risk from SQL, bind a view of your assets to the app's
-- input_assets reference (again, the UI uploads a file instead):
CALL <app>.SRC.UPDATE_REFERENCE(
  'input_assets', 'ADD',
  SYSTEM$REFERENCE('VIEW', '<your_db>.<your_schema>.<assets_view>', 'PERSISTENT', 'SELECT')
);

-- (no INIT step: granting EXECUTE MANAGED TASK above fires the app's grant
-- callback, which provisions the serverless run tasks automatically)

-- submit a run (returns a job id). Risk is not a separate task type: it is an
-- output of the emissions task, requested via the params `outputs` list plus
-- `scenarios` (and, optionally, `risk_years`).

-- emissions only:
CALL <app>.SRC.SUBMIT_TASK('emissions', {});

-- emissions + climate risk (writes both DATA.EMISSIONS and DATA.CLIMATE_RISK):
CALL <app>.SRC.SUBMIT_TASK('emissions', OBJECT_CONSTRUCT('outputs', ARRAY_CONSTRUCT('emissions','risk'), 'scenarios', ARRAY_CONSTRUCT('ipcc_net_zero','ngfs_net_zero'), 'risk_years', ARRAY_CONSTRUCT(2030, 2050)));

-- geospatial risk for every asset in the view bound to input_assets:
CALL <app>.SRC.SUBMIT_TASK('geospatial', {});

-- check progress:
SELECT * FROM <app>.DATA.TASKS ORDER BY TASK_ID DESC;

-- read results once the job is COMPLETED:
SELECT * FROM <app>.DATA.EMISSIONS;
SELECT * FROM <app>.DATA.CLIMATE_RISK;
SELECT * FROM <app>.DATA.GEOSPATIAL_RESULTS;

Engineer path (pure SQL)

For engineers building the analysis into a data pipeline, the sanctioned interface is pure SQL against your own view. The UI is for the CSV-upload workflow; the recipe below is the supported way to run the app from code.

The source parameter defaults to reference: the app reads the input_portfolio view you bind below without you passing anything extra.

The app has two input references, one per kind of input. input_portfolio is a view of holdings for the emissions task (steps 1 to 5). input_assets is a view of physical assets for the geospatial task (step 6). Each is bound once and stays bound; rebinding replaces the previous view.

  1. One-time reference bind. Bind your portfolio view to the app's input_portfolio reference (the UI does not use the reference; it works from an uploaded file). You need the privileges to grant the reference.
CALL <app>.SRC.UPDATE_REFERENCE(
  'input_portfolio', 'ADD',
  SYSTEM$REFERENCE('VIEW', '<db>.<schema>.<view>', 'PERSISTENT', 'SELECT')
);
  1. Discover the column contract. List the columns the input expects so you can build a column_map if your view uses different names. The returned object also carries asset_classes (the five display names in presentation order), identifier_meaning (what identifier is for each), and required_by_class (the columns each class requires); build your per-class checks off those keys rather than hard-coding a column list.
CALL <app>.SRC.GET_INPUT_CONTRACT();
  1. Submit a run. Because source defaults to reference, no source key is passed. Optionally supply column_map and/or classification_system.
CALL <app>.SRC.SUBMIT_TASK('emissions', OBJECT_CONSTRUCT('classification_system', 'GICS'));

To add climate risk, extend the same emissions task with an outputs list containing 'risk', a scenarios list (any of the 14 supported ids listed under Climate Risk), and the optional engineer-only risk_years param (defaults to [2030, 2035, 2040, 2045, 2050]). outputs selects whether the run computes emissions, risk, or both; a risk run always writes both DATA.EMISSIONS and DATA.CLIMATE_RISK. Risk additionally requires total_assets, ebitda, and net_debt on the input view.

CALL <app>.SRC.SUBMIT_TASK('emissions', OBJECT_CONSTRUCT('outputs', ARRAY_CONSTRUCT('emissions','risk'), 'scenarios', ARRAY_CONSTRUCT('ipcc_net_zero','ngfs_net_zero'), 'risk_years', ARRAY_CONSTRUCT(2030, 2035, 2040, 2045, 2050)));
  1. Choose the asset class. Asset class is a param on the same emissions task; there is no per-class task type, and nothing about the app's requested privileges changes when you use one. Pass asset_class for a single-class portfolio:
CALL <app>.SRC.SUBMIT_TASK('emissions', OBJECT_CONSTRUCT('asset_class', 'Public Equity'));

Or asset_class_column for a mixed portfolio, naming the column in your view that holds each row's class (the two params cannot be combined):

CALL <app>.SRC.SUBMIT_TASK('emissions', OBJECT_CONSTRUCT('asset_class_column', 'ASSET_CLASS'));

Both combine with everything above (outputs, scenarios, risk_years, column_map, classification_system) and with the optional prefer_reported flag:

CALL <app>.SRC.SUBMIT_TASK('emissions', OBJECT_CONSTRUCT('asset_class', 'Fixed Income', 'prefer_reported', TRUE, 'outputs', ARRAY_CONSTRUCT('emissions','risk'), 'scenarios', ARRAY_CONSTRUCT('ipcc_net_zero')));

Omitting both params runs the whole portfolio as Private Equity, so a pipeline written before this release keeps working untouched.

  1. Monitor and collect. Poll the task table, then read the results once the job is COMPLETED. Filter by ASSET_CLASS to separate the classes of a mixed run, and read EXCLUSIONS for anything the run could not use.
SELECT * FROM <app>.DATA.TASKS ORDER BY CREATED_DATETIME DESC;
SELECT TASK_ID, EXCLUSIONS FROM <app>.DATA.TASKS WHERE EXCLUSIONS IS NOT NULL;
SELECT * FROM <app>.DATA.EMISSIONS;
SELECT * FROM <app>.DATA.CLIMATE_RISK;
  1. Geospatial risk from SQL. Bind a view of your physical assets to the input_assets reference, then submit a geospatial task with no params. The view needs identifier, latitude, longitude and asset_value; owner_identifier and name are optional and carried through to the results when present (see Geospatial Risk for the column meanings). Every row in the view is run each time; results land in DATA.GEOSPATIAL_RESULTS under the run's TASK_ID, with SUBMISSION_ID set to input_assets so they can be told apart from runs submitted through the interface.
CALL <app>.SRC.UPDATE_REFERENCE(
  'input_assets', 'ADD',
  SYSTEM$REFERENCE('VIEW', '<db>.<schema>.<assets_view>', 'PERSISTENT', 'SELECT')
);
CALL <app>.SRC.SUBMIT_TASK('geospatial', {});
SELECT * FROM <app>.DATA.GEOSPATIAL_RESULTS WHERE TASK_ID = <task_id>;

Passing a submission_id param instead selects the interface's upload path; engineers do not need it.