Upload API Documentation

Overview

The TRACE Upload API lets you upload energy tariff offers to the system as JSON files. It supports Direct Marketing and PPA tariff types, each with their own pricing structures and capacity tier configurations. Uploaded offers use a versioning system — each new upload creates a new version, and the system always serves the most recent version to contract queries.

Authentication: All endpoints require a Bearer token. See Getting Started → Authentication for setup instructions.


Available Endpoints

Method Endpoint Description
POST /tariff-management/direct-marketing/upload Upload Direct Marketing tariff offers (EEG / Other, Spot / Market Value)
POST /tariff-management/ppa/upload Upload PPA tariff offers (Upstream / Downstream, Solar / Wind / Biomass)
POST /tariff-management/offers/schedules/contract-options Query available contract options by configuration and installed capacity

Endpoint Guides


How Price Upload Works

Versioning System

When you upload an offer with the same configuration (tariff type, technology, PPA structure, direct marketing type, etc.), the system:

  • Creates a new version of that offer
  • Keeps all previous versions in history (never deleted)
  • Uses the latest version (by CreatedAt timestamp) when querying for contract options

Uploading New Prices

Direct Marketing Example:

{
  "offer": {
    "name": "Solar EEG Spot Relative 0-1000kW",
    "tariffType": 3,
    "technology": "Solar",
    "configuration": {
      "directMarketingType": "EEG",
      "enumerationType": "Spot",
      "serviceFeeType": "Relative",
      "capacityTiers": [{ "min": 0, "max": 1000 }]
    },
    "priceMatrix": [
      { "start": "2026M02", "tenor": "11M", "prices": { ... } }
    ]
  }
}

PPA Example:

{
  "offer": {
    "name": "PPA Upstream Solar 100-500kW",
    "tariffType": 5,
    "technology": "Solar",
    "configuration": {
      "ppaStructure": "PayAsProduced",
      "guaranteeOfOrigin": "Provider",
      "negativePrices": "Excluded",
      "hedgeSharePercent": 100,
      "capacityTiers": [{ "min": 100, "max": 500 }]
    },
    "priceMatrix": [
      { "start": "2026Q1", "tenor": "1Y", "prices": { "2026": { "priceEurPerMWh": 85.0 } } }
    ]
  }
}

Updating Prices

To update prices for an existing configuration, upload a new offer with the same configuration but an updated priceMatrix. The new version will be used for all future queries.

Clearing Prices

To effectively "delete" prices for a specific configuration, upload an offer with an empty priceMatrix:

{
  "offer": {
    "name": "Solar EEG Spot Relative 0-1000kW - No Prices",
    "tariffType": 3,
    "technology": "Solar",
    "configuration": {
      "directMarketingType": "EEG",
      "enumerationType": "Spot",
      "serviceFeeType": "Relative",
      "capacityTiers": [{ "min": 0, "max": 1000 }]
    },
    "priceMatrix": []
  }
}

Result:

  • New version created with zero schedules
  • contract-options API will return this offer but with no available contracts
  • Old versions with prices remain in history

Querying Contract Options

How It Works

The contract-options API retrieves offers based on:

  1. Configuration match - tariffType, technology, directMarketingType/ppaStructure, etc.
  2. Capacity match - installedCapacity >= MinCapacity AND installedCapacity <= MaxCapacity
  3. Most recent version - Always uses the latest offer by CreatedAt timestamp

Capacity Range Behavior

Important: The system does NOT fall back to older versions. Only the most recent offer is considered.

Example Scenario:

Day 1: Upload offer with capacity 0-1000 kW and price 100 EUR/MWh

Day 2: Upload offer with capacity 0-500 kW and price 101 EUR/MWh

Query Result
installedCapacity: 400 Returns Day 2 offer (0-500 kW, price 101)
installedCapacity: 600 No offer found - Day 2 only covers 0-500 kW, Day 1 is ignored

Key Behaviors

Aspect Behavior
Versioning Each upload creates a new version (by CreatedAt timestamp)
Old Versions Remain in database but are not deleted and not used by default
Latest Version Always used by contract-options API
Empty PriceMatrix Allowed - creates offer with zero schedules (effectively "deletes" prices)
Capacity Filtering Only checks latest version; does not fall back to older versions
validAsOf Parameter Optional - retrieve offers valid as of a specific date (CreatedAt <= validAsOf)

Query Parameters

  • includeExpired: false - Filter out past contracts (default)
  • validAsOf: "2026-01-23T00:00:00Z" - Get offers valid as of specific date
  • installedCapacity: 400 - Filter by installed capacity

Example Queries

Direct Marketing:

POST /tariff-management/offers/schedules/contract-options
{
  "configuration": {
    "tariffType": 3,
    "technology": "Solar",
    "directMarketingType": "EEG",
    "installedCapacity": 400
  }
}

PPA:

POST /tariff-management/offers/schedules/contract-options
{
  "configuration": {
    "tariffType": 5,
    "technology": "Solar",
    "ppaStructure": "PayAsProduced",
    "guaranteeOfOrigin": "Provider",
    "negativePrices": "Excluded",
    "hedgeSharePercent": 100,
    "installedCapacity": 250
  }
}

Historical Query (using validAsOf):

POST /tariff-management/offers/schedules/contract-options
{
  "configuration": {
    "installedCapacity": 600
  },
  "validAsOf": "2026-01-22T23:59:59Z"
}

Common Features

File Format

  • Content-Type: multipart/form-data
  • File Format: JSON
  • Encoding: UTF-8

Upload Format

Both Direct Marketing and PPA support single and batch uploads:

Single:

{
  "offer": {
    "name": "Single Offer",
    ...
  }
}

Batch:

{
  "offers": [
    { "name": "Offer 1", ... },
    { "name": "Offer 2", ... }
  ]
}

Response Format

All endpoints return a standardized response:

{
  "success": true,
  "results": [
    {
      "offerId": "guid",
      "success": true,
      "message": "Imported successfully"
    }
  ]
}

Error Handling

  • 200 OK - Successful upload
  • 400 Bad Request - Invalid request or file format
  • 401 Unauthorized - Missing or invalid authentication
  • 500 Internal Server Error - Server error during processing

Best Practices

  1. Updating Prices: Upload a new offer with the same configuration but updated priceMatrix
  2. Removing Prices: Upload an offer with empty priceMatrix: []
  3. Capacity Changes: Be aware that narrowing capacity ranges will make larger capacities unavailable
  4. Historical Data: Use validAsOf parameter to retrieve offers from a specific date
  5. Testing: Always verify your uploads using the contract-options API

Troubleshooting

Issue: "No offers found" despite uploading prices

Solution: Check if the capacity range covers the requested installedCapacity. Remember that only the latest version is used.

Issue: Old prices still showing

Solution: This shouldn't happen - system always uses latest version. Check CreatedAt timestamps.

Issue: Want to restore old pricing

Solution: Re-upload the old offer JSON (will create a new version with old prices)

Issue: Need to delete an offer completely

Solution: Offers are never truly deleted. Upload an offer with empty priceMatrix to effectively clear prices, or filter at query time using validAsOf before the offer was created.


Getting Help

If you encounter issues:

  1. Check the specific tariff type documentation for detailed requirements
  2. Validate your JSON file format
  3. Review error messages in the API response
  4. Contact the TRACE development team for support