Direct Marketing Tariff Upload API - Complete User Guide
Overview
This guide explains how to upload Direct Marketing tariff offers to the system using JSON files. You can upload single or multiple offers with different configurations for capacity ranges, pricing models, and time periods.
Endpoint: POST /tariff-management/direct-marketing/upload
File Type: JSON uploaded as multipart/form-data
Note: For information on how versioning, price updates, and the contract-options API work, see the Price Upload Guide.
Table of Contents
- Quick Start
- What is a Direct Marketing Offer
- JSON Structure Overview
- Field Reference
- Complete JSON Examples - All Combinations
- How to Upload
- Response Format
- Validation Rules
- Common Mistakes
- Troubleshooting
Quick Start
- Create a JSON file with your Direct Marketing offer data
- Validate the JSON structure matches one of the examples below
- Upload using the API endpoint with Bearer authentication
- Check response for success or error messages
What is a Direct Marketing Offer
A Direct Marketing offer defines pricing and terms for selling energy through direct marketing contracts:
- Energy type: Solar or Wind
- Marketing model: EEG (German feed-in tariff) or Other
- Pricing basis: Spot market or Market Value
- Service fee model: Relative (percentage) or Absolute (fixed EUR/MWh)
- Capacity ranges: Optional tiers that create separate offers
- Time periods: Yearly or monthly pricing schedules
- Contract details: Start date and duration (tenor)
JSON Structure Overview
Single Offer Upload
{
"offer": {
"name": "Offer Name",
"tariffType": 3,
"countryCode": "DE",
"configuration": { ... },
"fees": { ... },
"priceMatrix": [ ... ],
"otherPriceComponents": { ... }
}
}
Batch Upload (Multiple Offers)
{
"offers": [
{ "name": "First Offer", ... },
{ "name": "Second Offer", ... }
]
}
Note: Use either offer (singular) or offers (plural), not both.
Field Reference
Root Level
| Field | Type | Required | Description |
|---|---|---|---|
offer |
object | Yes* | Single offer (for uploading one offer) |
offers |
array | Yes* | Array of offers (for batch upload) |
*Use one or the other, not both.
Offer Object
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
name |
string | Yes | Descriptive name for the offer | "Solar EEG Spot 2026" |
tariffType |
integer | Yes | Must be 3 for Direct Marketing |
3 |
countryCode |
string | Yes | ISO 3166-1 alpha-2 country code | "DE", "AT" |
description |
string | No | Optional detailed description | "EEG solar spot pricing" |
configuration |
object | Yes | Technical configuration | See below |
fees |
object | Yes | Default fee structure | See below |
priceMatrix |
array | Yes | Array of pricing contracts | See below |
otherPriceComponents |
object | Yes | Additional price components | See below |
Configuration Object
| Field | Type | Required | Allowed Values | Description |
|---|---|---|---|---|
technology |
string | Yes | "Solar", "Wind" |
Energy source type |
directMarketingType |
string | Yes | "EEG", "Other" |
Marketing contract type |
enumerationType |
string | Yes | "Spot", "MarketValue" |
Price calculation basis |
serviceFeeType |
string | Yes | "Relative", "Absolute" |
Fee calculation method |
capacityTiers |
array | No | Array of capacity ranges | Creates separate offers per tier |
Capacity Tiers
capacityTiers is an array of capacity range objects. Each tier creates a separate offer in the database.
Capacity Range Object:
| Field | Type | Required | Description |
|---|---|---|---|
min |
decimal | No | Minimum capacity in kW (defaults to 0 if omitted) |
max |
decimal | No | Maximum capacity in kW (use null for unlimited) |
Examples:
{ "min": 0, "max": 99 }→ Creates offer named "Your Offer (0-99kW)"{ "min": 100, "max": 249 }→ Creates offer named "Your Offer (100-249kW)"{ "min": 250, "max": null }→ Creates offer named "Your Offer (>250kW)"
Important Behavior:
- If
capacityTiersis provided with 3 tiers, 3 separate offers are created - If
capacityTiersis omitted, 1 offer is created with no capacity restrictions - All tiers share the same
priceMatrixschedules
Offer Uniqueness Requirements
Each offer must have a unique configuration in the system. You cannot upload two offers with identical configuration settings (same combination of technology, directMarketingType, enumerationType, serviceFeeType, and capacityTiers).
If you need to provide different pricing schedules, group them as multiple contracts within the priceMatrix array of a single offer rather than creating separate offers with the same configuration. This approach:
- Keeps related pricing options together under one offer
- Prevents duplicate configuration errors
- Makes offer management cleaner and more organized
Example: Instead of creating two separate "Solar EEG Spot" offers with different start dates, create one offer with multiple contracts in the priceMatrix array, each with its own start period and pricing schedule.
Fees Object
Default fees that apply to all pricing periods unless overridden:
| Field | Type | Required | Description |
|---|---|---|---|
guaranteeOfOriginFeeEurPerMWh |
decimal | No | Default Guarantee of Origin fee (EUR/MWh) |
basicFeePerYear |
decimal | No | Default annual basic fee (EUR) |
Price Matrix (Array of Contracts)
The priceMatrix is an array where each element represents a contract with a start period, duration (tenor), and pricing schedule.
Important: You can mix different time resolutions within the same priceMatrix. For example, you can have:
- One contract with yearly pricing ("2026", "2027", "2028")
- Another contract with monthly pricing ("2026M03", "2026M04", ...)
- Both in the same offer
This allows you to provide multiple contract options with different pricing granularities.
Contract Object:
| Field | Type | Required | Description |
|---|---|---|---|
start |
string | Yes | Start period: "YYYY" (yearly) or "YYYYMNN" (monthly) |
tenor |
string | No | Contract duration: "3Y", "12M", etc. (auto-calculated if omitted) |
prices |
object | Yes | Pricing schedule with period keys |
Start Period Formats:
- Yearly:
"2026","2027" - Monthly:
"2026M03"(March 2026),"2027M01"(January 2027)
Note: Direct Marketing supports yearly and monthly resolutions. Quarterly pricing is not supported (use PPA contracts for quarterly pricing).
Tenor Formats:
- Years:
"1Y","2Y","3Y" - Months:
"6M","12M","24M"
Prices Object:
Keys are period identifiers (matching the start format). Each period contains pricing fields:
| Field | Type | Required | Description |
|---|---|---|---|
fixedFeeEurPerMWh |
decimal | No | Fixed fee per MWh (EUR) |
marketValuePercent |
decimal | No | Market value percentage (for Spot enumeration) |
variableFixedFeeEurPerMWh |
decimal | No | Variable fixed fee per MWh (EUR) |
guaranteeOfOriginFeeEurPerMWh |
decimal | No | Override default GOO fee for this period |
basicFeePerYear |
decimal | No | Override default basic fee for this period |
Note: At least one pricing field must be provided per period.
Other Price Components Object
| Field | Type | Required | Allowed Values | Description |
|---|---|---|---|---|
basicFeePerYear |
string | Yes | "None", "Location factor" |
Additional fee component type |
Complete JSON Examples - All Combinations
1. Solar + Spot + Relative + Multiple Capacity Tiers
Most common scenario: Creates 3 separate offers with capacity-based pricing.
{
"offer": {
"name": "Solar EEG Spot 2026",
"tariffType": 3,
"countryCode": "DE",
"description": "Solar spot market pricing with capacity tiers",
"configuration": {
"technology": "Solar",
"directMarketingType": "EEG",
"enumerationType": "Spot",
"serviceFeeType": "Relative",
"capacityTiers": [
{ "min": 0, "max": 99 },
{ "min": 100, "max": 249 },
{ "min": 250, "max": null }
]
},
"fees": {
"guaranteeOfOriginFeeEurPerMWh": 0.5,
"basicFeePerYear": 180
},
"priceMatrix": [
{
"start": "2026",
"tenor": "3Y",
"prices": {
"2026": {
"fixedFeeEurPerMWh": 0,
"marketValuePercent": 1.99,
"variableFixedFeeEurPerMWh": 1.67
},
"2027": {
"fixedFeeEurPerMWh": 0,
"marketValuePercent": 2.05,
"variableFixedFeeEurPerMWh": 1.70
},
"2028": {
"fixedFeeEurPerMWh": 0,
"marketValuePercent": 2.10,
"variableFixedFeeEurPerMWh": 1.75
}
}
}
],
"otherPriceComponents": {
"basicFeePerYear": "None"
}
}
}
Result: Creates 3 database offers:
- "Solar EEG Spot 2026 (0-100kW)"
- "Solar EEG Spot 2026 (100-250kW)"
- "Solar EEG Spot 2026 (>250kW)"
Each offer has the same 3-year pricing schedule.
2. Wind + MarketValue + Absolute + No Capacity Tiers
Single offer without capacity restrictions: Creates 1 offer with absolute pricing.
{
"offer": {
"name": "Wind Market Value 2026",
"tariffType": 3,
"countryCode": "DE",
"description": "Wind market value with absolute service fees",
"configuration": {
"technology": "Wind",
"directMarketingType": "EEG",
"enumerationType": "MarketValue",
"serviceFeeType": "Absolute"
},
"fees": {
"guaranteeOfOriginFeeEurPerMWh": 0.3,
"basicFeePerYear": 200
},
"priceMatrix": [
{
"start": "2026",
"tenor": "2Y",
"prices": {
"2026": {
"fixedFeeEurPerMWh": 2.50
},
"2027": {
"fixedFeeEurPerMWh": 2.45
}
}
}
],
"otherPriceComponents": {
"basicFeePerYear": "Location factor"
}
}
}
Result: Creates 1 offer with no capacity restrictions.
3. Solar + Spot + Relative + Monthly Pricing (12 months)
Monthly granularity: 12-month contract with monthly price variations.
{
"offer": {
"name": "Solar Spot Monthly 2026",
"tariffType": 3,
"countryCode": "DE",
"description": "Monthly pricing for solar spot market",
"configuration": {
"technology": "Solar",
"directMarketingType": "EEG",
"enumerationType": "Spot",
"serviceFeeType": "Relative",
"capacityTiers": [
{ "min": 100, "max": 500 }
]
},
"fees": {
"guaranteeOfOriginFeeEurPerMWh": 0,
"basicFeePerYear": 180
},
"priceMatrix": [
{
"start": "2026M03",
"tenor": "12M",
"prices": {
"2026M03": {
"marketValuePercent": 1.95,
"variableFixedFeeEurPerMWh": 1.60
},
"2026M04": {
"marketValuePercent": 1.93,
"variableFixedFeeEurPerMWh": 1.58
},
"2026M05": {
"marketValuePercent": 1.90,
"variableFixedFeeEurPerMWh": 1.55
},
"2026M06": {
"marketValuePercent": 1.88,
"variableFixedFeeEurPerMWh": 1.52
},
"2026M07": {
"marketValuePercent": 1.85,
"variableFixedFeeEurPerMWh": 1.50
},
"2026M08": {
"marketValuePercent": 1.87,
"variableFixedFeeEurPerMWh": 1.52
},
"2026M09": {
"marketValuePercent": 1.90,
"variableFixedFeeEurPerMWh": 1.55
},
"2026M10": {
"marketValuePercent": 1.92,
"variableFixedFeeEurPerMWh": 1.57
},
"2026M11": {
"marketValuePercent": 1.94,
"variableFixedFeeEurPerMWh": 1.59
},
"2026M12": {
"marketValuePercent": 1.96,
"variableFixedFeeEurPerMWh": 1.61
},
"2027M01": {
"marketValuePercent": 1.98,
"variableFixedFeeEurPerMWh": 1.63
},
"2027M02": {
"marketValuePercent": 2.00,
"variableFixedFeeEurPerMWh": 1.65
}
}
}
],
"otherPriceComponents": {
"basicFeePerYear": "None"
}
}
}
Result: Creates 1 offer with monthly pricing from March 2026 to February 2027.
4. Solar + Spot + Relative + Multiple Contracts (Different Start Years)
Multiple pricing contracts: Different contracts starting at different times.
{
"offer": {
"name": "Solar Multi-Contract",
"tariffType": 3,
"countryCode": "DE",
"description": "Multiple contracts with different start dates",
"configuration": {
"technology": "Solar",
"directMarketingType": "EEG",
"enumerationType": "Spot",
"serviceFeeType": "Relative",
"capacityTiers": [
{ "min": 0, "max": 249 },
{ "min": 250, "max": null }
]
},
"fees": {
"guaranteeOfOriginFeeEurPerMWh": 0.5,
"basicFeePerYear": 180
},
"priceMatrix": [
{
"start": "2026",
"tenor": "2Y",
"prices": {
"2026": {
"marketValuePercent": 1.99,
"variableFixedFeeEurPerMWh": 1.67
},
"2027": {
"marketValuePercent": 2.05,
"variableFixedFeeEurPerMWh": 1.70
}
}
},
{
"start": "2027",
"tenor": "2Y",
"prices": {
"2027": {
"marketValuePercent": 2.10,
"variableFixedFeeEurPerMWh": 1.75
},
"2028": {
"marketValuePercent": 2.15,
"variableFixedFeeEurPerMWh": 1.80
}
}
},
{
"start": "2028",
"tenor": "1Y",
"prices": {
"2028": {
"marketValuePercent": 2.20,
"variableFixedFeeEurPerMWh": 1.85
}
}
}
],
"otherPriceComponents": {
"basicFeePerYear": "None"
}
}
}
Result: Creates 2 offers (due to 2 capacity tiers), each with 3 contract options (2026, 2027, 2028 starts).
5. Wind + MarketValue + Absolute + Fee Overrides
Per-period fee overrides: Different fees for different years.
{
"offer": {
"name": "Wind with Fee Overrides",
"tariffType": 3,
"countryCode": "DE",
"description": "Wind with year-specific fee adjustments",
"configuration": {
"technology": "Wind",
"directMarketingType": "EEG",
"enumerationType": "MarketValue",
"serviceFeeType": "Absolute"
},
"fees": {
"guaranteeOfOriginFeeEurPerMWh": 0.5,
"basicFeePerYear": 200
},
"priceMatrix": [
{
"start": "2026",
"tenor": "3Y",
"prices": {
"2026": {
"fixedFeeEurPerMWh": 2.50,
"guaranteeOfOriginFeeEurPerMWh": 0.3,
"basicFeePerYear": 150
},
"2027": {
"fixedFeeEurPerMWh": 2.45,
"guaranteeOfOriginFeeEurPerMWh": 0.3,
"basicFeePerYear": 150
},
"2028": {
"fixedFeeEurPerMWh": 2.40,
"guaranteeOfOriginFeeEurPerMWh": 0.3,
"basicFeePerYear": 150
}
}
}
],
"otherPriceComponents": {
"basicFeePerYear": "Location factor"
}
}
}
Result: Creates 1 offer. Each year uses overridden fees instead of defaults.
6. Solar + MarketValue + Absolute + Single Capacity Tier
One capacity tier: Creates a single offer with capacity restriction.
{
"offer": {
"name": "Solar Market Value Large",
"tariffType": 3,
"countryCode": "DE",
"description": "Large-scale solar installations only",
"configuration": {
"technology": "Solar",
"directMarketingType": "Other",
"enumerationType": "MarketValue",
"serviceFeeType": "Absolute",
"capacityTiers": [
{ "min": 1000, "max": null }
]
},
"fees": {
"guaranteeOfOriginFeeEurPerMWh": 0.2,
"basicFeePerYear": 300
},
"priceMatrix": [
{
"start": "2026",
"tenor": "3Y",
"prices": {
"2026": {
"fixedFeeEurPerMWh": 1.80
},
"2027": {
"fixedFeeEurPerMWh": 1.75
},
"2028": {
"fixedFeeEurPerMWh": 1.70
}
}
}
],
"otherPriceComponents": {
"basicFeePerYear": "None"
}
}
}
Result: Creates 1 offer named "Solar Market Value Large (>1000kW)".
7. Wind + Spot + Relative + Auto-Calculated Tenor
No tenor specified: System calculates tenor from the number of price periods.
{
"offer": {
"name": "Wind Spot Auto-Tenor",
"tariffType": 3,
"countryCode": "DE",
"description": "Contract with automatically calculated tenor",
"configuration": {
"technology": "Wind",
"directMarketingType": "EEG",
"enumerationType": "Spot",
"serviceFeeType": "Relative"
},
"fees": {
"guaranteeOfOriginFeeEurPerMWh": 0.4,
"basicFeePerYear": 220
},
"priceMatrix": [
{
"start": "2026",
"prices": {
"2026": {
"marketValuePercent": 2.00,
"variableFixedFeeEurPerMWh": 1.50
},
"2027": {
"marketValuePercent": 2.05,
"variableFixedFeeEurPerMWh": 1.55
}
}
}
],
"otherPriceComponents": {
"basicFeePerYear": "None"
}
}
}
Result: Creates 1 offer. Tenor is calculated as "2Y" (2 price periods).
8. Batch Upload - Multiple Offers at Once
Upload multiple offers in one request:
{
"offers": [
{
"name": "Solar Spot Small",
"tariffType": 3,
"countryCode": "DE",
"description": "Small solar installations",
"configuration": {
"technology": "Solar",
"directMarketingType": "EEG",
"enumerationType": "Spot",
"serviceFeeType": "Relative",
"capacityTiers": [
{ "min": 0, "max": 100 }
]
},
"fees": {
"guaranteeOfOriginFeeEurPerMWh": 0.5,
"basicFeePerYear": 150
},
"priceMatrix": [
{
"start": "2026",
"tenor": "1Y",
"prices": {
"2026": {
"marketValuePercent": 2.50,
"variableFixedFeeEurPerMWh": 2.00
}
}
}
],
"otherPriceComponents": {
"basicFeePerYear": "None"
}
},
{
"name": "Wind Market Value Large",
"tariffType": 3,
"countryCode": "DE",
"description": "Large wind installations",
"configuration": {
"technology": "Wind",
"directMarketingType": "EEG",
"enumerationType": "MarketValue",
"serviceFeeType": "Absolute",
"capacityTiers": [
{ "min": 1000, "max": null }
]
},
"fees": {
"guaranteeOfOriginFeeEurPerMWh": 0.3,
"basicFeePerYear": 300
},
"priceMatrix": [
{
"start": "2026",
"tenor": "3Y",
"prices": {
"2026": {
"fixedFeeEurPerMWh": 2.00
},
"2027": {
"fixedFeeEurPerMWh": 1.95
},
"2028": {
"fixedFeeEurPerMWh": 1.90
}
}
}
],
"otherPriceComponents": {
"basicFeePerYear": "Location factor"
}
}
]
}
Result: Creates 2 separate offers. Both are validated and imported in one request.
9. Solar + Spot + Relative + Mixed Time Resolutions (Yearly + Monthly)
Different time resolutions in the same priceMatrix: This example demonstrates that you can mix yearly and monthly contracts within the same offer. Each contract in the priceMatrix array can have its own time resolution.
{
"offer": {
"name": "Solar Mixed Pricing",
"tariffType": 3,
"countryCode": "DE",
"description": "Offers both yearly and monthly contract options",
"configuration": {
"technology": "Solar",
"directMarketingType": "EEG",
"enumerationType": "Spot",
"serviceFeeType": "Relative",
"capacityTiers": [
{ "min": 100, "max": 500 }
]
},
"fees": {
"guaranteeOfOriginFeeEurPerMWh": 0.5,
"basicFeePerYear": 180
},
"priceMatrix": [
{
"start": "2026",
"tenor": "3Y",
"prices": {
"2026": {
"marketValuePercent": 1.99,
"variableFixedFeeEurPerMWh": 1.67
},
"2027": {
"marketValuePercent": 2.05,
"variableFixedFeeEurPerMWh": 1.70
},
"2028": {
"marketValuePercent": 2.10,
"variableFixedFeeEurPerMWh": 1.75
}
}
},
{
"start": "2026M06",
"tenor": "6M",
"prices": {
"2026M06": {
"marketValuePercent": 1.85,
"variableFixedFeeEurPerMWh": 1.50
},
"2026M07": {
"marketValuePercent": 1.83,
"variableFixedFeeEurPerMWh": 1.48
},
"2026M08": {
"marketValuePercent": 1.85,
"variableFixedFeeEurPerMWh": 1.50
},
"2026M09": {
"marketValuePercent": 1.88,
"variableFixedFeeEurPerMWh": 1.52
},
"2026M10": {
"marketValuePercent": 1.90,
"variableFixedFeeEurPerMWh": 1.55
},
"2026M11": {
"marketValuePercent": 1.92,
"variableFixedFeeEurPerMWh": 1.57
}
}
}
],
"otherPriceComponents": {
"basicFeePerYear": "None"
}
}
}
Result: Creates 1 offer with two contract options at different time resolutions:
- Contract 1: 3-year contract with yearly pricing (2026, 2027, 2028)
- Contract 2: 6-month contract with monthly pricing (June-November 2026)
This demonstrates that the same priceMatrix can contain contracts with different time granularities.
10. Wind + Spot + Absolute + Minimal Fields
Minimum required fields only:
{
"offer": {
"name": "Wind Spot Minimal",
"tariffType": 3,
"countryCode": "DE",
"configuration": {
"technology": "Wind",
"directMarketingType": "Other",
"enumerationType": "Spot",
"serviceFeeType": "Absolute"
},
"fees": {},
"priceMatrix": [
{
"start": "2026",
"prices": {
"2026": {
"fixedFeeEurPerMWh": 2.00
}
}
}
],
"otherPriceComponents": {
"basicFeePerYear": "None"
}
}
}
Result: Creates 1 offer with minimal configuration. No default fees, single year pricing.
How to Upload
Using cURL (Command Line)
curl -X POST "https://your-api-domain.com/tariff-management/direct-marketing/upload" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: multipart/form-data" \
-F "file=@your-offer.json"
Using PowerShell
$filePath = 'C:\path\to\your-offer.json'
$uri = 'https://your-api-domain.com/tariff-management/direct-marketing/upload'
$headers = @{ Authorization = 'Bearer YOUR_TOKEN' }
$form = @{ file = Get-Item $filePath }
Invoke-RestMethod -Uri $uri -Method Post -Headers $headers -Form $form
Using Postman
- Method: POST
- URL:
https://your-api-domain.com/tariff-management/direct-marketing/upload - Headers:
Authorization: Bearer YOUR_TOKEN
- Body:
- Select
form-data - Key:
file(change type toFile) - Value: Select your JSON file
- Select
- Send
Using JavaScript (Fetch API)
const formData = new FormData();
formData.append('file', fileInput.files[0]);
fetch('https://your-api-domain.com/tariff-management/direct-marketing/upload', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN'
},
body: formData
})
.then(response => response.json())
.then(data => console.log('Success:', data))
.catch(error => console.error('Error:', error));
Response Format
Success Response
When using capacityTiers, multiple results are returned - one per tier:
{
"success": true,
"results": [
{
"offerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"success": true,
"message": "Imported successfully"
},
{
"offerId": "7bc12d89-8a23-4c71-9def-5e432a1b8c92",
"success": true,
"message": "Imported successfully"
},
{
"offerId": "9de45c01-2f34-4a87-8bcd-4d567e8f9a01",
"success": true,
"message": "Imported successfully"
}
]
}
Without Capacity Tiers
Single result when no tiers are specified:
{
"success": true,
"results": [
{
"offerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"success": true,
"message": "Imported successfully"
}
]
}
Batch Upload Response
Multiple results for batch uploads:
{
"success": true,
"results": [
{
"offerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"success": true,
"message": "Imported successfully"
},
{
"offerId": "7bc12d89-8a23-4c71-9def-5e432a1b8c92",
"success": true,
"message": "Imported successfully"
}
]
}
Error Response
If validation fails:
{
"success": false,
"results": [
{
"offerId": null,
"success": false,
"message": "Validation failed: TariffType must be 3 for Direct Marketing"
}
]
}
Validation Rules
Required Fields
✓ offer or offers must be present
✓ name, tariffType, countryCode required for each offer
✓ configuration with all 4 fields: technology, directMarketingType, enumerationType, serviceFeeType
✓ fees object (can be empty {})
✓ priceMatrix with at least one contract
✓ Each contract must have start and prices
✓ otherPriceComponents with basicFeePerYear field
Field Validation
✓ tariffType must be 3
✓ countryCode must be valid ISO 3166-1 alpha-2 (2 letters)
✓ Enum values must match exactly (case-sensitive): "Solar", "Wind", "EEG", "Other", "Spot", "MarketValue", "Relative", "Absolute"
✓ Period keys in prices must match start format (yearly: "YYYY", monthly: "YYYYMNN")
Capacity Tiers
✓ If provided, min must be less than max (when both are non-null)
✓ min and max must be non-negative
✓ Tiers can be omitted entirely (creates single offer without capacity restrictions)
Pricing
✓ At least one pricing field per period entry ✓ Decimal values must be valid numbers
Contract Logic
✓ tenor is optional (auto-calculated from price periods if omitted)
✓ Multiple contracts can have overlapping or different time ranges
Common Mistakes
Wrong tariffType
"tariffType": 1 // WRONG - 1 is not Direct Marketing
Fix:
"tariffType": 3 // Correct for Direct Marketing
Using numeric enums instead of strings
"technology": 0, // WRONG - Deprecated format
"directMarketingType": 1, // WRONG - Deprecated format
"enumerationType": 0, // WRONG - Deprecated format
"serviceFeeType": 0 // WRONG - Deprecated format
Fix:
"technology": "Solar",
"directMarketingType": "EEG",
"enumerationType": "Spot",
"serviceFeeType": "Relative"
Using capacityRange in priceMatrix
"priceMatrix": [
{
"start": "2026",
"capacityRange": { "min": 0, "max": 100 }, // WRONG - Deprecated format
"prices": { ... }
}
]
Fix:
"configuration": {
...
"capacityTiers": [
{ "min": 0, "max": 100 } // Correct format
]
},
"priceMatrix": [
{
"start": "2026",
"prices": { ... } // No capacityRange here
}
]
Missing required pricing field
"prices": {
"2026": {} // WRONG - No pricing fields
}
Fix:
"prices": {
"2026": {
"fixedFeeEurPerMWh": 2.00 // At least one field required
}
}
Mismatched period keys
{
"start": "2026", // Yearly format
"prices": {
"2026M01": { ... } // WRONG - Monthly format doesn't match
}
}
Fix:
{
"start": "2026",
"prices": {
"2026": { ... }, // Match yearly format
"2027": { ... }
}
}
Using both offer and offers
{
"offer": { ... }, // WRONG - Can't use both
"offers": [ ... ]
}
Fix (choose one):
// For single offer:
{
"offer": { ... }
}
// For batch:
{
"offers": [ ... ]
}
Invalid month format
"start": "2026M3" // WRONG - Month must be 2 digits
Fix:
"start": "2026M03" // Correct
Can I mix yearly and monthly contracts in the same offer?
Yes! You can have multiple contracts with different time resolutions in the same priceMatrix:
"priceMatrix": [
{
"start": "2026",
"tenor": "2Y",
"prices": {
"2026": { ... }, // Yearly
"2027": { ... } // Yearly
}
},
{
"start": "2026M06",
"tenor": "6M",
"prices": {
"2026M06": { ... }, // Monthly
"2026M07": { ... }, // Monthly
"2026M08": { ... } // Monthly
}
}
]
This creates one offer with two contract options at different time granularities.
Troubleshooting
Issue: "TariffType must be 3"
Cause: You used a different tariff type number.
Fix: Set "tariffType": 3
Issue: "Invalid enumeration value"
Cause: Used numeric values (0, 1) instead of strings, or misspelled enum.
Fix: Use exact strings: "Solar", "Wind", "EEG", "Other", "Spot", "MarketValue", "Relative", "Absolute"
Issue: "Capacity range validation failed"
Cause: Deprecated format used (capacityRange inside priceMatrix contract).
Fix: Move capacity ranges to configuration.capacityTiers (correct format).
Issue: "No pricing fields provided"
Cause: Empty prices object for a period.
Fix: Add at least one pricing field: fixedFeeEurPerMWh, marketValuePercent, variableFixedFeeEurPerMWh, etc.
Issue: "Invalid JSON format"
Cause: Syntax error in JSON (missing comma, bracket, etc.). Fix: Validate JSON at jsonlint.com or use a JSON validator.
Issue: Multiple offers created unexpectedly
Cause: You provided capacityTiers in correct format.
Explanation: This is expected behavior. Each tier creates a separate offer.
Fix (if unwanted): Remove capacityTiers to create single offer without capacity restrictions.
Issue: "Tenor calculation failed"
Cause: Provided invalid or inconsistent price periods.
Fix: Ensure price period keys are sequential and match the start format. Or explicitly provide tenor.
Summary Checklist
Before uploading:
- JSON file is valid (use validator)
-
tariffTypeis3 - All configuration fields use string values (not numbers)
-
capacityTiersinconfiguration(not inpriceMatrixcontracts) - correct format - At least one pricing field per period in
prices - Period keys match
startformat (yearly or monthly) -
otherPriceComponents.basicFeePerYearis set to"None"or"Location factor" - File encoding is UTF-8
- Authentication token is ready
Last Updated: December 2025
Endpoint: /tariff-management/direct-marketing/upload