Reonic Planning Templates API
Small groups of [**Components**](#tag/components) that can be added to targeted planning sections when a project type or requirement calls for extra components.
Small groups of [**Components**](#tag/components) that can be added to targeted planning sections when a project type or requirement calls for extra components.
openapi: 3.1.0
info:
title: Reonic REST Api v3 Activities Planning Templates API
description: 'The Reonic REST API v3 provides programmatic access to create and manage resources. The API follows REST principles and returns responses in JSON format. Authentication is required via an API key passed in the X-Authorization header.
## Errors
All endpoints return errors with the same JSON shape:
```json
{ "message": "human-readable description" }
```
`400` responses additionally include an `errors` field with per-field validation details.
The HTTP status code identifies the cause:
| Status | Meaning | When |
|--------|---------|------|
| `400` | Bad Request | Path params, query string, or request body failed validation. Inspect `errors` for the field-level breakdown. |
| `401` | Unauthorized | The `X-Authorization` header is missing, malformed, does not match an active API key, or belongs to a different API version. The response never indicates which check failed; check that the key matches the endpoint version. API v3 endpoints require a v3 key with the `rnc_v3_` prefix. |
| `403` | Forbidden | The API key is read-only and the request targeted a write endpoint (`POST`). Issue a key with write access. |
| `404` | Not Found | A resource referenced by a path id does not exist or is not visible to your workspace. |
| `429` | Too Many Requests | The per-client rate limit was exceeded. See **Rate limiting** below. |
| `500` | Internal Server Error | Unexpected failure. Safe to retry once; if it persists, contact support. |
| `503` | Service Unavailable | A backing dependency is temporarily unavailable. Retry with exponential backoff. |
## Rate limiting
Limits are shared across all API keys you hold and reset on a 1-minute window. Two buckets:
| Bucket | Limit | Applies to |
|--------|-------|------------|
| `cached` | 500 / min | `GET` requests served from the response cache |
| `uncached` | 30 / min | Cache misses, `GET` requests sent with `Reonic-Cache-Control: no-cache`, and all `POST` requests |
Every response includes:
- `X-RateLimit-Bucket` — `cached` or `uncached`
- `X-RateLimit-Limit` — the bucket''s ceiling (`500` or `30`)
- `X-RateLimit-Remaining` — calls left in the current window
- `X-RateLimit-Reset` — Unix epoch seconds at which the window resets
- `X-RateLimit-Policy` — `<limit>;w=60`
`429` responses additionally set `Retry-After` (in seconds). Wait at least that long before retrying.
## Caching and Reonic-Cache-Control
`GET` responses are cached for up to 1 hour. Identical requests (same path and query) on the same API key return the cached result. To force a fresh read, send `Reonic-Cache-Control: no-cache`; the response is then refreshed and re-cached. Forced refreshes count against the `uncached` rate-limit bucket.
The standard `Cache-Control` header is not honored. Use `Reonic-Cache-Control` to control caching behavior.
## Authentication
Every request must include your API key in the `X-Authorization` header:
```
X-Authorization: <your-api-key>
```
API keys are issued from the Reonic web app and look like `rnc_v3_…`. Send the full value, including the prefix.
'
version: 3.2.0
contact:
email: kontakt@reonic.de
url: https://reonic.com
name: Reonic GmbH
servers:
- url: '{apiBaseUrl}/rest/v3/'
security:
- X-Authorization: []
tags:
- name: Planning Templates
description: Small groups of [**Components**](#tag/components) that can be added to targeted planning sections when a project type or requirement calls for extra components.
paths:
/planningTemplates:
get:
summary: List planning templates
description: 'List all planning templates. A planning template is a small group of components that can be added to targeted planning sections when a project type or requirement calls for extra components.
**Allowed API keys:** Read-only, Read and Write'
tags:
- Planning Templates
parameters:
- schema:
type: array
items:
type: string
enum:
- all
- residential
- residentialSolar
- residentialEvCharger
- residentialBatteryStorage
- residentialHotWaterStorage
- residentialHeatingStorage
- residentialHeating
- residentialHeatPump
- residentialAccessoryToHeatPump
- residentialOptionalComponents
- residentialAdditionalComponents
- commercial
- commercialSolar
- commercialBatteryStorage
- commercialLandlordToTenant
- commercialPowerPurchaseAgreement
- commercialAdditionalComponents
description: Filter by planning templates matching at least one target.
required: false
description: Filter by planning templates matching at least one target.
style: form
explode: false
name: target
in: query
- schema:
type: string
enum:
- exclude
- include
- only
default: exclude
description: 'Controls whether inactive planning templates appear in results. Default: exclude.'
required: false
description: 'Controls whether inactive planning templates appear in results. Default: exclude.'
name: inactive
in: query
- schema:
type: string
example: no-cache
required: false
name: Reonic-Cache-Control
in: header
description: Set to 'no-cache' to bypass the 1-hour response cache and force a fresh read. The fresh response is then written back to the cache for subsequent callers. Forced refreshes count against the uncached rate-limit bucket (30/min); only cache hits count against the cached bucket (500/min).
responses:
'200':
description: List of all planning templates
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/PlanningTemplate'
description: List of items
required:
- data
/planningTemplates/{templateId}:
get:
summary: Get planning template
description: 'Get a single planning template by its ID.
**Allowed API keys:** Read-only, Read and Write'
tags:
- Planning Templates
parameters:
- schema:
type: string
format: uuid
required: true
name: templateId
in: path
- schema:
type: string
example: no-cache
required: false
name: Reonic-Cache-Control
in: header
description: Set to 'no-cache' to bypass the 1-hour response cache and force a fresh read. The fresh response is then written back to the cache for subsequent callers. Forced refreshes count against the uncached rate-limit bucket (30/min); only cache hits count against the cached bucket (500/min).
responses:
'200':
description: The planning template
content:
application/json:
schema:
$ref: '#/components/schemas/PlanningTemplate'
/planningTemplates/create:
post:
summary: Create planning template
description: 'Create a new planning template.
**Allowed API keys:** Read and Write'
tags:
- Planning Templates
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PlanningTemplateCreate'
responses:
'201':
description: The created planning template
content:
application/json:
schema:
$ref: '#/components/schemas/PlanningTemplate'
/planningTemplates/{templateId}/update:
post:
summary: Update planning template
description: 'Update an existing planning template. Omit a field to leave it unchanged; send `null` on nullable fields to clear them.
**Allowed API keys:** Read and Write'
tags:
- Planning Templates
parameters:
- schema:
type: string
format: uuid
required: true
name: templateId
in: path
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PlanningTemplateUpdate'
responses:
'200':
description: The updated planning template
content:
application/json:
schema:
type: object
properties:
data:
$ref: '#/components/schemas/PlanningTemplate'
required:
- data
components:
schemas:
PlanningTemplate:
type: object
properties:
id:
type: string
format: uuid
example: 123e4567-e89b-12d3-a456-426614174000
name:
type: string
description:
type:
- string
- 'null'
active:
type: boolean
description: Determines if the planning template can be imported into an offer or not.
targets:
type: array
items:
type: string
enum:
- all
- residential
- residentialSolar
- residentialEvCharger
- residentialBatteryStorage
- residentialHotWaterStorage
- residentialHeatingStorage
- residentialHeating
- residentialHeatPump
- residentialAccessoryToHeatPump
- residentialOptionalComponents
- residentialAdditionalComponents
- commercial
- commercialSolar
- commercialBatteryStorage
- commercialLandlordToTenant
- commercialPowerPurchaseAgreement
- commercialAdditionalComponents
description: Planning sections or project contexts where this template can be applied.
items:
type: array
items:
type: object
properties:
id:
type: string
format: uuid
description: Identifier for this Planning Template Item. For the linked Component's ID, see `component.id`.
example: 123e4567-e89b-12d3-a456-426614174000
component:
type: object
properties:
id:
type: string
format: uuid
description: Reference to [**Components**](#tag/components)
example: 123e4567-e89b-12d3-a456-426614174000
versionId:
type: string
format: uuid
description: Exact component version referenced by the planning template.
example: 123e4567-e89b-12d3-a456-426614174000
source:
type: string
enum:
- catalog
- custom
description: '`catalog` for reusable components from the component catalog; `custom` for template-specific custom components.'
required:
- id
- versionId
- source
quantity:
type: number
purchasePrice:
type:
- number
- 'null'
description: Cost paid to acquire the component, net (excluding VAT). Null when not tracked.
salesPrice:
type: number
description: Unit price charged to the end customer, net (excluding VAT). Pinned on this item; later edits to the catalog component do not propagate.
vatRate:
type: number
minimum: 0
maximum: 1
description: VAT rate as a fraction (e.g. 0.19 for 19%). Pinned on this item; later edits to the catalog component do not propagate.
salesPriceSource:
type: string
enum:
- component
- planningTemplate
description: 'How `salesPrice` was set when this item was created or last updated: `component` if it was snapshotted from the catalog component''s price at that time, `planningTemplate` if it was set explicitly on this item. Both values are equally pinned afterwards.'
position:
type: number
description: Order of the item within the planning template.
visibleToCustomer:
type: boolean
required:
- id
- component
- quantity
- purchasePrice
- salesPrice
- vatRate
- salesPriceSource
- position
- visibleToCustomer
createdAt:
type:
- string
- 'null'
format: date-time
example: '2026-01-01T15:30:00.000Z'
createdById:
type:
- string
- 'null'
format: uuid
updatedAt:
type:
- string
- 'null'
format: date-time
example: '2026-01-01T15:30:00.000Z'
updatedById:
type:
- string
- 'null'
format: uuid
required:
- id
- name
- description
- active
- targets
- items
- createdAt
- createdById
- updatedAt
- updatedById
PlanningTemplateUpdate:
type: object
properties:
name:
type: string
minLength: 1
maxLength: 500
description:
type:
- string
- 'null'
maxLength: 5000
description: Send `null` to clear; omit to leave unchanged.
active:
type: boolean
targets:
type: array
items:
type: string
enum:
- all
- residential
- residentialSolar
- residentialEvCharger
- residentialBatteryStorage
- residentialHotWaterStorage
- residentialHeatingStorage
- residentialHeating
- residentialHeatPump
- residentialAccessoryToHeatPump
- residentialOptionalComponents
- residentialAdditionalComponents
- commercial
- commercialSolar
- commercialBatteryStorage
- commercialLandlordToTenant
- commercialPowerPurchaseAgreement
- commercialAdditionalComponents
minItems: 1
description: Planning sections or project contexts where this template can be applied. Provided array fully replaces the existing targets; omit to leave them unchanged.
items:
type: array
items:
oneOf:
- $ref: '#/components/schemas/PlanningTemplateCatalogItemInput'
- $ref: '#/components/schemas/PlanningTemplateCustomItemInput'
discriminator:
propertyName: componentSource
mapping:
catalog: '#/components/schemas/PlanningTemplateCatalogItemInput'
custom: '#/components/schemas/PlanningTemplateCustomItemInput'
description: 'Provided array fully replaces the existing items; `[]` removes all items; omit to leave items unchanged. Array order becomes the planning template item order. Each item references either a catalog component (`componentSource: "catalog"`) or inline-creates a template-specific custom component (`componentSource: "custom"`). Custom components hold commercial data only and do not feed into the system-size or simulation figures shown in the Portal — see `componentSource`.'
additionalProperties: false
PlanningTemplateCatalogItemInput:
type: object
properties:
componentSource:
type: string
enum:
- catalog
description: Reference an existing entry from [**Components**](#tag/components) by ID.
componentId:
type: string
format: uuid
description: ID of the [**Components**](#tag/components) entry to add. The latest component version is used.
example: 123e4567-e89b-12d3-a456-426614174000
quantity:
type: number
exclusiveMinimum: 0
visibleToCustomer:
type: boolean
default: true
salesPrice:
type: number
minimum: 0
description: Unit price charged to the end customer, net (excluding VAT). Omit (together with `vatRate`) to snapshot the catalog component's current price. The value is pinned on this item — later edits to the catalog component do not propagate.
vatRate:
type: number
minimum: 0
maximum: 1
description: VAT rate as a fraction (e.g. 0.19 for 19%). Omit (together with `salesPrice`) to snapshot the catalog component's current VAT rate. The value is pinned on this item — later edits to the catalog component do not propagate.
required:
- componentSource
- componentId
- quantity
additionalProperties: false
PlanningTemplateCreate:
type: object
properties:
name:
type: string
minLength: 1
maxLength: 500
description:
type:
- string
- 'null'
maxLength: 5000
active:
type: boolean
default: false
targets:
type: array
items:
type: string
enum:
- all
- residential
- residentialSolar
- residentialEvCharger
- residentialBatteryStorage
- residentialHotWaterStorage
- residentialHeatingStorage
- residentialHeating
- residentialHeatPump
- residentialAccessoryToHeatPump
- residentialOptionalComponents
- residentialAdditionalComponents
- commercial
- commercialSolar
- commercialBatteryStorage
- commercialLandlordToTenant
- commercialPowerPurchaseAgreement
- commercialAdditionalComponents
minItems: 1
description: Planning sections or project contexts where this template can be applied.
items:
type: array
items:
oneOf:
- $ref: '#/components/schemas/PlanningTemplateCatalogItemInput'
- $ref: '#/components/schemas/PlanningTemplateCustomItemInput'
discriminator:
propertyName: componentSource
mapping:
catalog: '#/components/schemas/PlanningTemplateCatalogItemInput'
custom: '#/components/schemas/PlanningTemplateCustomItemInput'
description: 'Full initial item list. Array order becomes the planning template item order. Omit to create the template without items. Each item references either an existing catalog component (`componentSource: "catalog"`) or inline-creates a template-specific custom component (`componentSource: "custom"`). Custom components hold commercial data only and do not feed into the system-size or simulation figures shown in the Portal — see `componentSource`.'
required:
- name
- targets
additionalProperties: false
PlanningTemplateCustomItemInput:
type: object
properties:
componentSource:
type: string
enum:
- custom
description: 'Inline-create a template-specific custom component as part of this item. A custom component stores only commercial fields (name, description, price, VAT, quantity) — it has no technical specifications. It therefore contributes nothing to the system-size and simulation figures the Portal derives from components (e.g. kWp peak power, storage capacity, yield) and those values will appear empty there. If you need a component to feed into system size or simulation, reference a catalog component with `componentSource: "catalog"` instead.'
componentType:
type: string
enum:
- module
- inverter
- microinverter
- optimizer
- virtualBattery
- batteryStorage
- evCharger
- heatPump
- airHeatPump
- hotWaterHeatPump
- heatingStorage
- hotWaterStorage
- heatingRod
- radiator
- indoorUnitAirHeatPump
- accessoryToEvCharger
- accessoryToHeatPump
- accessoryToModule
- accessoryToInverter
- accessoryToBatteryStorage
- other
- moduleFrameConstruction
- serviceFee
- installationFee
default: other
description: Category of the inline component; sets how it is grouped in offers (e.g. `module` → solar, `batteryStorage` → storage). Defaults to `other`. This only affects grouping — it does not give the custom component the technical specs of that category (see `componentSource`).
name:
type: string
minLength: 1
maxLength: 500
description:
type:
- string
- 'null'
maxLength: 5000
quantity:
type: number
exclusiveMinimum: 0
visibleToCustomer:
type: boolean
default: true
salesPrice:
type: number
minimum: 0
description: Effective unit price charged to the end customer, net (excluding VAT).
vatRate:
type: number
minimum: 0
maximum: 1
description: VAT rate as a fraction (e.g. 0.19 for 19%).
required:
- componentSource
- name
- quantity
- salesPrice
- vatRate
additionalProperties: false
securitySchemes:
X-Authorization:
type: apiKey
in: header
name: X-Authorization
x-tagGroups:
- name: People
tags:
- Contacts
- Users
- Teams
- name: Projects
tags:
- Residential Projects
- Commercial Projects
- name: Working on a project
tags:
- Notes
- Tasks
- Files
- File Folders
- Activities
- Time Tracking
- Checklists
- Checklist Templates
- Signature Requests
- name: Calendar
tags:
- Calendars
- Calendar Categories
- Appointments
- name: Catalog
tags:
- Components
- Planning Templates
- Planning Packages
- Offer Templates
- name: Workspace setup
tags:
- Kanban Boards
- Kanban Columns
- Tags
- Lead Sources
- name: Wiki
tags:
- Wiki
- name: Services
tags:
- Photogrammetry
- name: API helpers
tags:
- Upload
- Links
- name: Integrations
tags:
- Webhooks
- name: Guides
tags:
- Migrating from API v2 to v3
- Changelog