Upload API Documentation
Overview
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
Direct Marketing
Upload EEG and Other direct marketing offers with capacity tiers, Spot or Market Value pricing, and absolute or relative service fees.
PPA
Upload Upstream and Downstream Power Purchase Agreement offers for Solar, Wind, and Biomass with flexible payment structures and Guarantee of Origin options.
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
CreatedAttimestamp) 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-optionsAPI 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:
- Configuration match - tariffType, technology, directMarketingType/ppaStructure, etc.
- Capacity match -
installedCapacity >= MinCapacity AND installedCapacity <= MaxCapacity - Most recent version - Always uses the latest offer by
CreatedAttimestamp
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 dateinstalledCapacity: 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
- Updating Prices: Upload a new offer with the same configuration but updated
priceMatrix - Removing Prices: Upload an offer with empty
priceMatrix: [] - Capacity Changes: Be aware that narrowing capacity ranges will make larger capacities unavailable
- Historical Data: Use
validAsOfparameter to retrieve offers from a specific date - Testing: Always verify your uploads using the
contract-optionsAPI
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:
- Check the specific tariff type documentation for detailed requirements
- Validate your JSON file format
- Review error messages in the API response
- Contact the TRACE development team for support